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's 的孩子是从多个类继承的,那么就会有模棱两可typedef的 s。

问题:添加像空继承这样的接口class _special,是否会以任何方式损害当前代码(例如对象结构、编译错误等)?

4

3 回答 3

3

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

就个人而言,我会在外部实施这种分类。模板专业化不会获得从 special 派生的类的期望结果,也间接被认为是特殊的。看起来您正在使用 C++11,所以我会这样做:

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

并替换is_base_of<T, _special>decltype( is_special( static_cast<T*>(0) ) ). sizeof在 C++03 中,可以通过让分类函数返回不同大小的类型来实现相同的技巧:

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

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

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

于 2011-10-09T08:32:52.253 回答
3

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

如果您使用的是单继承,则对象的布局将像第一个基类一样布局第一个内存,然后是用于保存链中后续类成员的内存。如果你有任何虚函数,也会有一个地方,可能在开头,用于虚拟指针。如果您从另一种类型派生一种类型,则通常需要遵循“三规则”:虚拟析构函数、复制构造函数和复制赋值运算符。那么你将有一个虚拟指针,这可能是 4 个字节,没什么大不了的。

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

也就是说,请考虑是否要使用继承来对此进行建模。也许给对象一个 bool 成员变量是个好主意。

于 2011-10-09T08:33:05.600 回答
0

not sure what you mean with hurt or object structuring (care to elaborate?), but there should be no compiler errors, instantiation/constructor of the classed deriving from _special does not change since _special has a default constructor and perfomance-wise the compiler might apply empty base class optimization.

That being said, the option of using typedefs to tag classes might be a better, clearer and more extendible solution. And just as ambiguous as A's children inheriting form multiple other classes that all might inherit from _special.

于 2011-10-09T08:26:29.670 回答