C+上的部分类定义+;? 谁知道C++上有可能有部分类定义?< /P>

C+上的部分类定义+;? 谁知道C++上有可能有部分类定义?< /P>,c++,C++,比如: 文件1.h: class Test { public: int test1(); }; 课堂测试{ 公众: int test1(); }; 文件2.h: class Test { public: int test2(); }; 课堂测试{ 公众: int test2(); }; 对我来说,它对于定义多平台类非常有用,这些类之间具有与平台无关的公共函数,因为继承是一种对多平台类没有用处的代价 我的意思是,在运行时,您永远不会有两个多平台专门化

比如:

文件1.h:

class Test { public: int test1(); }; 课堂测试{ 公众: int test1(); }; 文件2.h:

class Test { public: int test2(); }; 课堂测试{ 公众: int test2(); }; 对我来说,它对于定义多平台类非常有用,这些类之间具有与平台无关的公共函数,因为继承是一种对多平台类没有用处的代价

我的意思是,在运行时,您永远不会有两个多平台专门化实例,只有在编译时。继承可能有助于满足您的公共接口需求,但在此之后,它不会在运行时添加任何有用的内容,只会增加成本

此外,您还必须使用丑陋的ifdef来使用该类,因为您无法从抽象类生成实例:

class genericTest { public: int genericMethod(); }; 类泛型测试{ 公众: int genericMethod(); }; 那么让我们假设对于win32:

class win32Test: public genericTest { public: int win32Method(); }; 类win32Test:公共泛型测试{ 公众: int win32Method(); }; 也许:

class macTest: public genericTest { public: int macMethod(); }; macTest类:公共泛型测试{ 公众: int macMethod(); }; 假设win32Method()和macMethod()都调用genericMethod(),您必须像这样使用该类:

#ifdef _WIN32 genericTest *test = new win32Test(); #elif MAC genericTest *test = new macTest(); #endif test->genericMethod(); #ifdef_WIN32 genericTest*测试=新的win32Test(); #艾利夫麦克 genericTest*测试=新的macTest(); #恩迪夫 测试->通用方法(); 现在想一想,继承只在为它们提供一个依赖于特定平台的genericMethod()时才有用,但是您需要为此调用两个构造函数。此外,代码中还散布着丑陋的ifdef

这就是为什么我在寻找部分课程。我可以在编译时定义特定的依赖于平台的部分结束,当然,在这个愚蠢的示例中,我仍然需要一个丑陋的“ifdef inside genericMethod(),但还有其他方法可以避免这种情况。

尝试继承

具体地

class AllPlatforms {
public:
    int common();
};
然后

class PlatformA : public AllPlatforms {
public:
    int specific();
};

<>这是不可能的C++,它会给你一个错误,关于重新定义已经定义的类。如果您想共享行为,请考虑继承。< /p> 如所写,不可能。

您可能需要查看名称空间。可以将函数添加到另一个文件的命名空间中。类的问题是每个.cpp都需要查看类的完整布局。


但是,您可能需要查找一种称为“策略类”的技术。基本上,您可以创建微类(它们本身没有用处),然后在以后的某个时候将它们粘在一起。

两次声明类主体可能会产生类型重新定义错误。如果你在找工作的话。我建议使用杰米来隐藏平台特定的细节。< /P> < P>要么使用继承,如使用的,要么用IFIFF来在不同的平台上编译不同的部分。

< P>因为头只是文本插入,其中一个可以省略“类测试{”和“}”,并且包含在另一个中间。

我在生产代码中看到了这一点,尽管不是Delphi,不是C++。这让我特别恼火,因为它破坏了IDE的代码导航功能

对我来说,它对于定义多平台类似乎非常有用,这些类之间具有与平台无关的公共函数

除了开发人员几十年来一直在这样做,没有这个“特性”

我相信创建partial是因为微软几十年来一直有一个坏习惯,即生成代码并将其交给开发人员进行开发和维护

生成的代码通常是维护的噩梦。当您需要升级MFC版本时,整个MFC生成的框架有哪些习惯?或者,在升级Visual Studio时,如何将所有代码移植到*.designer.cs文件中

大多数其他平台更依赖于生成用户/开发人员可以修改的配置文件。它们的词汇量比较有限,不容易与无关的代码混合。如果认为有必要,配置文件甚至可以作为资源文件插入到二进制文件中


我从未见过在继承或配置资源文件无法更好地工作的地方使用“partial”。

使用模板专门化和partial专门化可以得到类似于partial类的东西。在投入太多时间之前,请检查编译器对这些的支持。MSC++6.0等较旧的编译器不支持部分专门化。

或者您可以尝试PIMPL

通用头文件:

class Test
{
public:
    ...
    void common();
    ...
private:
    class TestImpl;
    TestImpl* m_customImpl;
};
然后创建cpp文件,执行特定于平台的自定义实现。

如何:

class WindowsFuncs { public: int f(); int winf(); };
class MacFuncs { public: int f(); int macf(); }

class Funcs
#ifdef Windows 
    : public WindowsFuncs
#else
    : public MacFuncs
#endif
{
public:
    Funcs();
    int g();
};

现在的代码>函数> /COD>是编译时已知的类,所以抽象基类或任何东西都不造成开销。

< P>不能部分定义C++中的类。

#include will work as that is preprocessor stuff.

class Foo
{
#include "FooFile_Private.h"
}

////////

FooFile_Private.h:

private:
  void DoSg();
这里有一种方法可以获得您想要的“多态性,其中只有一个子类”效果,而不需要额外的开销,并且只需要最少的#定义或代码重复。这称为模拟动态绑定:

template <typename T>
class genericTest {
public:
    void genericMethod() {
        // do some generic things
        std::cout << "Could be any platform, I don't know" << std::endl;
        // base class can call a method in the child with static_cast
        (static_cast<T*>(this))->doClassDependentThing();
    }
};

#ifdef _WIN32
    typedef Win32Test Test;
#elif MAC
    typedef MacTest Test;
#endif
模板
类泛型测试{
公众:
void genericMethod(){
//做一些普通的事情
标准::cout

这在C++中是不可能的,它会给你一个关于重新定义已经定义的错误。 类。如果您想共享行为,请考虑继承。

我同意这一点。分部类是一种奇怪的构造,这使得以后很难维护。很难找到每个成员声明的分部类,很难避免重新定义甚至重新实现特性

如果要扩展std::vector,则必须从它继承。这是因为以下几个原因。首先,更改类的责任和(正确地)其类不变量。其次,从安全角度来看,应该避免这样做。 考虑一个处理用户身份验证的类…

partial class UserAuthentication {
  private string user;
  private string password;
  public bool signon(string usr, string pwd);
}

partial class UserAuthentication {
  private string getPassword() { return password; }
}
还有很多其他原因
class MacTest : public genericTest<MacTest> {
public:
    void macMethod() {
        // mac-specific stuff:
        std::cout << "I'm in MacOS" << std::endl;
        // we can call a method in the base class
        genericMethod();
        // more mac-specific stuff...
    }
    void doClassDependentThing() {
        std::cout << "Yep, definitely in MacOS" << std::endl;
    }
};
#ifdef _WIN32
    typedef genericTest<Win32Test> BaseTest;
#elif MAC
    typedef genericTest<MacTest> BaseTest;
#endif
partial class UserAuthentication {
  private string user;
  private string password;
  public bool signon(string usr, string pwd);
}

partial class UserAuthentication {
  private string getPassword() { return password; }
}
#ifndef TEST_H
#define TEST_H

class Test
{
public:
    Test(void);
    virtual ~Test(void);

#include "Test_Partial_Win32.h"
#include "Test_Partial_OSX.h"

};

#endif // !TEST_H
// This file should be included in Test.h only.

#ifdef MAC
    public:
        int macMethod();
#endif // MAC
// This file should be included in Test.h only.

#ifdef _WIN32
    public:
        int win32Method();
#endif // _WIN32
// Implement common member function of class Test in this file.

#include "stdafx.h"
#include "Test.h"

Test::Test(void)
{
}

Test::~Test(void)
{
}
// Implement OSX platform specific function of class Test in this file.

#include "stdafx.h"
#include "Test.h"

#ifdef MAC
int Test::macMethod()
{
    return 0;
}
#endif // MAC
// Implement WIN32 platform specific function of class Test in this file.

#include "stdafx.h"
#include "Test.h"

#ifdef _WIN32
int Test::win32Method()
{
    return 0;
}
#endif // _WIN32
template <typename TResource, typename TParams, typename TKey>
class IResource
{
public:
    virtual TKey GetKey() const = 0;
protected:
    static shared_ptr<TResource> Create(const TParams& params)
    {
        return ResourceManager::GetInstance().Load(params);
    }
    virtual Status Initialize(const TParams& params, const TKey key, shared_ptr<Viewer> pViewer) = 0;
};
template <typename TResource, typename TParams, typename TKey>
class TResourceManager
{
    sptr<TResource> Load(const TParams& params) { ... }
};
class Texture2D : public IResource<Texture2D , Params::Texture2D , Key::Texture2D >
{
    typedef TResourceManager<Texture2D , Params::Texture2D , Key::Texture2D > ResourceManager;
    friend class ResourceManager;

public:
    virtual Key::Texture2D GetKey() const override final;
    void GetWidth() const;
private:
    virtual Status Initialize(const Params::Texture2D & params, const Key::Texture2D key, shared_ptr<Texture2D > pTexture) override final;

    struct Impl;
    unique_ptr<Impl> m;
};
// D3DTexture2DImpl.h
#include "Texture2D.h"
struct Texture2D::Impl
{
    /* insert D3D-specific stuff here */
};

// OGLTexture2DImpl.h
#include "Texture2D.h"
struct  Texture2D::Impl
{
    /* insert OGL-specific stuff here */
};

// Texture2D.cpp
#include "Texture2D.h"

#ifdef USING_D3D
#include "D3DTexture2DImpl.h"
#else
#include "OGLTexture2DImpl.h"
#endif

Key::Texture2D Texture2D::GetKey() const
{
    return m->key;
}
// etc...
class MyClass
{
   #include <MyClass_Part1.hpp>
   #include <MyClass_Part2.hpp>
   #include <MyClass_Part3.hpp>
};