没有数据成员的派生 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,具有许多不同的存储模型。 classesClassAClassB这两个派生纯粹是对同一行为添加不同的实现,不包含任何数据。它 应该 在不调用任何副本的情况下将对 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 实例,由组成 AorBAB 共享。这种方法意味着您需要创建一个 class 来知道您可能想要浏览哪些子类型。这对您来说可能是问题,也可能不是问题,具体取决于您的用例。

策略

一种更灵活的方法可能是将AB视为策略,将Base视为上下文。在这种方法中,您不会使用继承。可以把数据和接口分开,这样AB可以继承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 是它唯一的朋友。