任何人都知道是否可以在C++上进行部分类定义?
就像是:
file1.h:
class Test { public: int test1(); };
file2.h:
class Test { public: int test2(); };
对我而言,定义具有与平台无关的通用功能的多平台类似乎非常有用,因为继承是一种对多平台类无用的支付成本.
我的意思是,在运行时,您将永远不会有两个多平台特化实例,仅在编译时.继承可能对满足您的公共接口需求很有用,但之后它不会在运行时添加任何有用的东西,只需要成本.
此外,您将不得不使用丑陋的#ifdef来使用该类,因为您无法从抽象类创建实例:
class genericTest { public: int genericMethod(); };
然后让我们说win32:
class win32Test: public genericTest { public: int win32Method(); };
有可能:
class macTest: public genericTest { public: int macMethod(); };
我们认为win32Method()和macMethod()都调用genericMethod(),你必须使用这样的类:
#ifdef _WIN32 genericTest *test = new win32Test(); #elif MAC genericTest *test = new macTest(); #endif test->genericMethod();
现在想一下继承只对它们提供一个依赖于特定于平台的genericMethod()有用,但是由于这个原因你需要花费两个构造函数.你的代码周围也散布着丑陋的#ifdef.
这就是为什么我在寻找部分课程.我可以在编译时定义特定平台依赖的部分结束,当然,在这个愚蠢的例子中,我仍然需要一个丑陋的#ifdef在genericMethod()中,但还有另一种方法可以避免这种情况.
这在C++中是不可能的,它会给你一个关于重新定义已经定义的类的错误.如果您想分享行为,请考虑继承.
尝试继承
特别
class AllPlatforms { public: int common(); };
然后
class PlatformA : public AllPlatforms { public: int specific(); };
您无法在C++中部分定义类.
这是一种获得"多态性,只有一个子类"的方法,你可以在没有开销的情况下使用#define或代码重复.它被称为模拟动态绑定:
templateclass genericTest { public: void genericMethod() { // do some generic things std::cout << "Could be any platform, I dunno" << std::endl; // base class can call a method in the child with static_cast (static_cast (this))->doClassDependentThing(); } }; #ifdef _WIN32 typedef Win32Test Test; #elif MAC typedef MacTest Test; #endif
然后在其他一些标题中关闭:
class Win32Test : public genericTest{ public: void win32Method() { // windows-specific stuff: std::cout << "I'm in windows" << std::endl; // we can call a method in the base class genericMethod(); // more windows-specific stuff... } void doClassDependentThing() { std::cout << "Yep, definitely in windows" << std::endl; } };
和
class MacTest : public genericTest{ 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; } };
这在编译时为您提供了适当的多态性.genericTest可以以一种给它平台版本的方式非虚拟地调用doClassDependentThing(几乎就像一个虚方法),当win32Method调用genericMethod时,它当然会获得基类版本.
这不会产生与虚拟调用相关的开销 - 您可以获得相同的性能,就好像您输入了两个没有共享代码的大类一样.它可能会在con(de)struction中创建一个非虚拟的调用开销,但如果内联的cont(de)结构被内联你应该没问题,并且这种开销在任何情况下都不会比使用被调用的genericInit方法更糟糕.两个平台.
客户端代码只是创建Test的实例,并且可以调用它们的方法,这些方法可以是genericTest,也可以是平台的正确版本.为了帮助代码中的类型安全而不关心平台并且不想意外地使用特定于平台的调用,您还可以执行以下操作:
#ifdef _WIN32 typedef genericTestBaseTest; #elif MAC typedef genericTest BaseTest; #endif
你必须要小心使用BaseTest,但不比C++中的基类总是如此.例如,不要使用错误判断的传值来对其进行切片.并且不要直接实例化它,因为如果你这样做并调用最终尝试"假虚拟"调用的方法,那么你就麻烦了.后者可以通过确保所有genericTest的构造函数都受到保护来实施.
或者你可以试试PIMPL
公共头文件:
class Test { public: ... void common(); ... private: class TestImpl; TestImpl* m_customImpl; };
然后创建执行特定于平台的自定义实现的cpp文件.
#include will work as that is preprocessor stuff. class Foo { #include "FooFile_Private.h" } //////// FooFile_Private.h: private: void DoSg();