C++ 在派生 class 中替换基 class
C++ replace base class in derived class
我相信我正在考虑这个 "badly"(非 C++'y)。这是我正在尝试做的事情
class AA {
public:
AA(const char* name, unsigned short number);
int Write(int x);
...
}
class BB: public AA {
public:
BB(const char* name, unsigned short number, const char* other);
BB(AA aaObj, const char* other);
int Write(double y, int x) {
/* do something */
AA::Write(x)
}
...
}
在第二个 BB 构造函数中,我想用 aaObj 替换 BB 的基础对象。我不想要副本,我希望实际的基础对象相同(相同的引用)。
问题:
- 这可能吗?
- 这是个坏主意吗?
- 是否有更好的模式(工厂生产具有共享成员的对象?
这是不可能的。想想 class 层次结构,例如 nesting dolls。派生的 class 是外面的那个,每个连续的基础 class 是一个嵌套的娃娃。由于基础 classes 包含在派生 class 中,因此您不能使用另一个基础 class 作为派生对象的基础 class。
如果您希望多个对象共享同一个对象,您可以做的一件事是使用 std::shared_ptr
成员。这样每个对象都可以有一个指向同一个对象的指针。
每个派生实例都有自己的任何基础实例class,你无法绕过这个。要使派生类型引用相同的基实例,需要将其从派生 is-a 关系更改为成员 has-a(然后该成员需要是引用或指针)。
我在那个职位上会做的事情是这样的:
class BB{
public:
BB(AA& aaObj, const char* other)
{
basepointer = &aaobj;
}
int Write(double y, int x) {
basepointer->Write(x);
}
private:
AA* basepointer;
};
这两个 class 在内存布局上 通常 彼此不匹配(例如,您可能在 BB
中有其他数据成员)。此外,由于您在构造函数中,您已经在创建一个新对象。
除非您确定 AA
最初是 BB
class(或 [=13= 的子 class,否则您不能向下转换为 BB
]).例如:
BB b;
AA * a = dynamic_cast<AA *> (&b);
/* use initialization code for AA on a */
/* Now you could do (though this example becomes a bit weird): */
BB *bb = dynamic_cast<BB *> (a);
为什么要避免复制?你有大量的数据成员吗?在这种情况下,请考虑使用 shared_ptr
on the relevant class members and implement an assignment-operator。所以这样做:
AA a;
/* ... */
BB b;
b = a;
或
BB b(a)
成为分配 shared_ptr
的唯一问题,因此非常便宜。
简单回答您的问题:
不是当前形式,可能是通过 down 铸造。但是这个
可能是一个糟糕的设计。
是的。应该是吧。
- 如果您有很多成员,例如字符串等,请考虑:保留对
AA
的引用,将 AA
复制到 BB
(这可能不是很大的成本),重构这样你就可以
直接实例化 BB
而是将 upward 发送到 AA
到您的初始化例程。
为了提供更详细的建议,我们需要更多关于您尝试优化的特定问题的代码或信息。
从问题的描述来看,您似乎想要组合而不是继承。 特别是 这样你的 Write
函数就不是虚函数了(重载非虚函数只在 CRTP 设计中有意义,而你的 class 不是 CRTP) .
然后,如果你切换到合成,你可以使用一个指向拥有对象的(智能)指针,并随意替换它。
我相信我正在考虑这个 "badly"(非 C++'y)。这是我正在尝试做的事情
class AA {
public:
AA(const char* name, unsigned short number);
int Write(int x);
...
}
class BB: public AA {
public:
BB(const char* name, unsigned short number, const char* other);
BB(AA aaObj, const char* other);
int Write(double y, int x) {
/* do something */
AA::Write(x)
}
...
}
在第二个 BB 构造函数中,我想用 aaObj 替换 BB 的基础对象。我不想要副本,我希望实际的基础对象相同(相同的引用)。
问题:
- 这可能吗?
- 这是个坏主意吗?
- 是否有更好的模式(工厂生产具有共享成员的对象?
这是不可能的。想想 class 层次结构,例如 nesting dolls。派生的 class 是外面的那个,每个连续的基础 class 是一个嵌套的娃娃。由于基础 classes 包含在派生 class 中,因此您不能使用另一个基础 class 作为派生对象的基础 class。
如果您希望多个对象共享同一个对象,您可以做的一件事是使用 std::shared_ptr
成员。这样每个对象都可以有一个指向同一个对象的指针。
每个派生实例都有自己的任何基础实例class,你无法绕过这个。要使派生类型引用相同的基实例,需要将其从派生 is-a 关系更改为成员 has-a(然后该成员需要是引用或指针)。
我在那个职位上会做的事情是这样的:
class BB{
public:
BB(AA& aaObj, const char* other)
{
basepointer = &aaobj;
}
int Write(double y, int x) {
basepointer->Write(x);
}
private:
AA* basepointer;
};
这两个 class 在内存布局上 通常 彼此不匹配(例如,您可能在 BB
中有其他数据成员)。此外,由于您在构造函数中,您已经在创建一个新对象。
除非您确定 AA
最初是 BB
class(或 [=13= 的子 class,否则您不能向下转换为 BB
]).例如:
BB b;
AA * a = dynamic_cast<AA *> (&b);
/* use initialization code for AA on a */
/* Now you could do (though this example becomes a bit weird): */
BB *bb = dynamic_cast<BB *> (a);
为什么要避免复制?你有大量的数据成员吗?在这种情况下,请考虑使用 shared_ptr
on the relevant class members and implement an assignment-operator。所以这样做:
AA a;
/* ... */
BB b;
b = a;
或
BB b(a)
成为分配 shared_ptr
的唯一问题,因此非常便宜。
简单回答您的问题:
不是当前形式,可能是通过 down 铸造。但是这个 可能是一个糟糕的设计。
是的。应该是吧。
- 如果您有很多成员,例如字符串等,请考虑:保留对
AA
的引用,将AA
复制到BB
(这可能不是很大的成本),重构这样你就可以 直接实例化BB
而是将 upward 发送到AA
到您的初始化例程。
为了提供更详细的建议,我们需要更多关于您尝试优化的特定问题的代码或信息。
从问题的描述来看,您似乎想要组合而不是继承。 特别是 这样你的 Write
函数就不是虚函数了(重载非虚函数只在 CRTP 设计中有意义,而你的 class 不是 CRTP) .
然后,如果你切换到合成,你可以使用一个指向拥有对象的(智能)指针,并随意替换它。