【发布时间】:2017-11-03 21:41:21
【问题描述】:
假设我有课
class A {
protected:
int x,y;
double z,w;
public:
void foo();
void bar();
void baz();
};
在我的代码和其他人的代码中定义和使用。现在,我想写一些库,它可以很好地对 A 进行操作,但它实际上更通用,并且能够操作:
class B {
protected:
int y;
double z;
public:
void bar();
};
我确实希望我的库是通用的,所以我定义了一个 B 类,这就是它的 API 所采用的。
我希望能够告诉编译器——不是在我不再控制的 A 的定义中,而是在其他地方,可能在 B 的定义中:
看,请尝试将
B视为A的超类。因此,特别是,将它放在内存中,这样如果我将A*重新解释为B*,我的代码期望B*s 就可以工作。然后请实际接受A*作为B*(和A&作为B&等)。
在 C++ 中,我们可以用另一种方式做到这一点,即如果 B 是我们无法控制的类,我们可以使用 class A : public B { ... } 执行“子类化已知类”操作;而且我知道 C++ 没有相反的机制——“通过新的 B 类对已知的 A 类进行超类化”。我的问题是 - 这种机制最接近的可实现近似值是什么?
注意事项:
- 这都是严格的编译时,而不是运行时。
-
class A可能没有任何更改。我只能修改B的定义和知道A和B的代码。其他人仍将使用A类,如果我希望我的代码与他们的代码交互,我也会如此。 - 这应该最好“可扩展”到多个超类。所以也许我也有
class C { protected: int x; double w; public: void baz(); },它的行为也应该像A的超类。
【问题讨论】:
-
那么,您希望
A从B继承而不实际更改A? -
你的
class B不是更多的合同吗?那么你能在消费库端使用概念/模板吗? -
@Galik CRTP 只有在基础和派生都知道发生了什么的情况下才有用。
A不是模板,所以不能使用 CRTP 继承它,它已经不继承自B。 -
如果编译器只是新的如何直接从
A转换为B,而不是使用类似继承的指针,它会起作用吗?如果是这样,那么在B,你可以写一个隐式转换构造函数。 -
@ZdeněkJelínek 可能有最好的主意。您不需要语言定义的实际合同;只需将所有需要
B的东西都设为模板,并表现得像所有必需的成员都在那里。否则编译将失败。
标签: c++ superclass subclassing idioms