2011-10-09 59 views
3

在代码中有一些特殊的类,并且有一些正常的类。我想区分它们,因为需要给予不同的待遇。所有这些特殊类基地(不是任何其他类的孩子)额外的继承对对象结构或实例化有什么影响吗?

为了实现这个目标,我令牌化在源代码中特殊class ES通过和空struct将继承对他们说:

struct _special {}; // empty class 
class A : public _special { // A becomes special 
... 
}; 
class B { // 'B' remains normal 
... 
}; 
class D : public A { // 'D' becomes special due to 'A' 
... 
}; 

每当需要,我可以找到使用is_base_of<Base,Derived>分离特殊和普通类。替代的方法是一直使用typedef特殊类中的:

class A { 
    public: typedef something _special; 
}; 

的问题是,如果A的孩子是从多个类继承,然后会有暧昧typedef秒。

问题:添加这种接口如继承与空class _special,将它它伤害以任何方式的当前代码(例如对象的结构化,编译错误等)?

回答

0

不知道你的意思与伤害对象结构(注意详细点吗?),但应该没有编译器错误,实例化/构造的归类从_special派生不会改变,因为_special有一个默认构造函数和性能方面,编译器可能会应用空基类优化。这就是说,使用typedefs来标记类的选项可能是一个更好,更清晰和更可扩展的解决方案。就像A的孩子继承多个其他类一样,它们都可能从_special继承。

3

大多数(如果不是所有的)体面编译器对简单情况都实现空基优化(EBO),这意味着您的对象大小不会通过从空基继承而增长。然而,当一个类以不止一种方式从空的基地继承时,由于需要针对相同类型的不同空白基地具有不同的地址,优化可能是不可能的。为了防止这种情况发生,通常会将空白基底作为将派生类作为参数的模板,但这会使is_base_of不可用。

就我个人而言,我会在外部实现这种分类。模板专门化不会得到类间接被认为特殊的派生类的期望结果。它看起来像你正在使用C++ 11所以我会做:

std::false_type is_special(...); 
std::true_type is_special(A const*); 

而且随着decltype(is_special(static_cast<T*>(0)))取代is_base_of<T, _special>。在C由具有分类函数的返回类型不同尺寸的++ 03同样可以与sizeof特技来实现:

typedef char no_type; 
struct yes_type { no_type _[2]; }; 

no_type is_special(...); 
yes_type is_special(A const*); 

并与sizeof(is_special(static_cast<T*>(0))) == sizeof(yes_type)替换is_base_of<T, _special>。您可以在辅助类模板中包装分类检查。

+0

很好的回答,但我没有使用C++ 11。 – iammilind

+0

@iammilind:你仍然可以使用类型特征:) –

+0

@iammilind:C++ 03解决方案现在包括在内。 –

3

内存中对象的布局只在C++标准中部分指定,但是大多数编译器都使用某些约定。空类型会占用一点内存(所以它们将有一个内存地址,这会给它们的指针标识)。这些额外的内存通常只有四个字节,在大多数情况下不需要担心。如果您从另一方面的空类型继承,它不应该增加对象的大小,因为对象的其余部分将占用空间,因此无论如何它都会有地址。

如果使用单继承的对象将与存储器的第一比特被布置类似于第一基类进行布局,然后将内存来保存后的类的成员在链中。如果你有任何虚函数,虚拟指针也会有一个地方,可能在开头。如果你从另一个类型派生出一个类型,你通常会遵循“三个规则”:一个虚拟析构函数,复制构造函数和复制赋值操作符。那么你将有一个虚拟指针,这可能是4个字节,没有什么大不了的。

如果你进入多重继承,那么你的对象开始在结构上变得非常复杂。他们会有各种指向自己不同部分的指针,以便函数可以找到他们正在寻找的成员。

这就是说,考虑是否要使用继承来在所有建模。也许给对象一个bool成员变量将是一个好主意。