我正在使用的库定义了一个抽象基类A
,其中包含~10个纯虚方法。没有公开定义的非纯方法,我怀疑A
没有私有数据,即类只是一个接口。该库还定义了一些A
的具体子类,例如C
。
我想为A
添加一些功能,以便其所有子类继承此功能。但是,A
在库中定义,我不能这样做。
相反,我已经定义了一个新的B
子类。这个子类不是具体的,A
的所有纯虚方法都是孤立的。它定义了一些新的辅助方法,它们调用A
定义的方法。 B
也没有定义任何字段。
为了使用B
来增强C
实例的功能,我已经完成了以下操作,我怀疑这是不能保证的行为。
C
的对象。B*
类型。B
定义的方法。这样安全吗?对象是在堆上创建的,所以我认为不会发生任何切片。如果安全性取决于A
和C
定义的字段,那么需要哪些要求来保证此行为?
如果A
和C
都没有自己的数据而不是vpointer,这会安全吗?
如果C
只有自己的数据呢?
编辑:我应该补充一点,我尝试过这种行为至少似乎是我想要的行为。我没有描述内存泄漏。
答案 0 :(得分:1)
整个事情看起来像代码味道给我。我将采用包装类的B类方法:在构造函数中获取A *指针,将所需的调用转发给A *。然后你可以将C *传递给那个构造函数,它将通过B析构函数中的“delete”正确删除。
答案 1 :(得分:0)
以下是关于我的评论的一个想法。它的行为符合预期,可能是一些隐藏的危险,但对我来说,只要bar
没有任何数据,这似乎是合理的。
#include <iostream>
struct base {
int x = 1;
int y = 2;
void show() {
std::cout << x + y << std::endl;
}
virtual void virt() = 0;
};
struct foo : base {
int a = 5;
int b = 2;
void print() {
std::cout << a + b << std::endl;
x++;
}
void virt() override {
std::cout << "foo" << std::endl;
}
};
template <typename T>
struct bar : T {
void print2() {
std::cout << T::a * T::b << std::endl;
T::b++;
T::x++;
T::virt();
}
};
template <typename Base>
bar<Base>* extend_with_bar(Base& base) {
return static_cast<bar<Base>*>(&base);
}
int main() {
foo f;
f.show();
f.print();
auto b = extend_with_bar(f);
b->print2();
b->print2();
b->print();
f.print();
b->show();
f.show();
b->virt();
}