没有数据成员的派生 class 的参考提升
Reference promotion for a derived class with no data members
我有一个有趣的问题涉及我维护的库中的 classes 层次结构。一个非常简单的情况如下:
class Base {
// private data + public interface to said data
};
class ClassA : public Base {
// Behaviour
};
class ClassB : public Base {
// Behaviour
};
所以这里我有一个 class,它私下包含数据并具有一致的接口。实际上,这是一个模板化的 class,具有许多不同的存储模型。 classesClassA
和ClassB
这两个派生纯粹是对同一行为添加不同的实现,不包含任何数据。它 应该 在不调用任何副本的情况下将对 ClassA
的实例的引用转换为 ClassB
之一的可能性范围内。当然可以用
ClassA a;
B& a_bref = *reintepret_cast<B*>(&a);
但这打破了所有规则。我的问题:是否有安全的方法来实现这样的转换运算符?
多重继承
实现目标的一种方法是通过多重继承。
class A : virtual public Base {
//...
};
class B : virtual public Base {
//...
};
class AorB : public A, public B {
//...
};
使用虚拟继承,您只有一个 Base
实例,由组成 AorB
的 A
和 B
共享。这种方法意味着您需要创建一个 class 来知道您可能想要浏览哪些子类型。这对您来说可能是问题,也可能不是问题,具体取决于您的用例。
策略
一种更灵活的方法可能是将A
和B
视为策略,将Base
视为上下文。在这种方法中,您不会使用继承。可以把数据和接口分开,这样A
和B
可以继承accessor方法,但是引用数据。
class Base {
friend class Base_Interface;
//...
};
class Base_Interface {
Base &context_;
//...
Base_Interface (Base &context) : context_(context) {}
template <typename X> operator X () { return context_; }
};
class A : public Base_Interface {
//...
A (Base &context) : Base_Interface(context) {}
};
class B : public Base_Interface {
//...
B (Base &context) : Base_Interface(context) {}
};
也许是懒惰的,有一个模板转换方法允许 Base_Interface
的用户转换为在其构造函数中接受 Base
的其他 class。如果 Base
没有 public 成员,并且 Base_Interface
是它唯一的朋友。
我有一个有趣的问题涉及我维护的库中的 classes 层次结构。一个非常简单的情况如下:
class Base {
// private data + public interface to said data
};
class ClassA : public Base {
// Behaviour
};
class ClassB : public Base {
// Behaviour
};
所以这里我有一个 class,它私下包含数据并具有一致的接口。实际上,这是一个模板化的 class,具有许多不同的存储模型。 classesClassA
和ClassB
这两个派生纯粹是对同一行为添加不同的实现,不包含任何数据。它 应该 在不调用任何副本的情况下将对 ClassA
的实例的引用转换为 ClassB
之一的可能性范围内。当然可以用
ClassA a;
B& a_bref = *reintepret_cast<B*>(&a);
但这打破了所有规则。我的问题:是否有安全的方法来实现这样的转换运算符?
多重继承
实现目标的一种方法是通过多重继承。
class A : virtual public Base {
//...
};
class B : virtual public Base {
//...
};
class AorB : public A, public B {
//...
};
使用虚拟继承,您只有一个 Base
实例,由组成 AorB
的 A
和 B
共享。这种方法意味着您需要创建一个 class 来知道您可能想要浏览哪些子类型。这对您来说可能是问题,也可能不是问题,具体取决于您的用例。
策略
一种更灵活的方法可能是将A
和B
视为策略,将Base
视为上下文。在这种方法中,您不会使用继承。可以把数据和接口分开,这样A
和B
可以继承accessor方法,但是引用数据。
class Base {
friend class Base_Interface;
//...
};
class Base_Interface {
Base &context_;
//...
Base_Interface (Base &context) : context_(context) {}
template <typename X> operator X () { return context_; }
};
class A : public Base_Interface {
//...
A (Base &context) : Base_Interface(context) {}
};
class B : public Base_Interface {
//...
B (Base &context) : Base_Interface(context) {}
};
也许是懒惰的,有一个模板转换方法允许 Base_Interface
的用户转换为在其构造函数中接受 Base
的其他 class。如果 Base
没有 public 成员,并且 Base_Interface
是它唯一的朋友。