虚拟分配
virtual assignment
我在理解这个问题时遇到了一些麻烦。
我有一堂课:
class StringProperty { //snipped...
protected:
std::string s;
public:
virtual StringProperty& operator= (const std::string &x) {
s = x;
return *this;
}
virtual StringProperty& foo(const std::string &x) {
s = x;
return *this;
}
};
这个类(有更多的方法,为了简单起见被截取(应该充当字符串。
当我从中得出时:
class Test : public StringProperty { };
我想做这样的事情:
Test x;
x = "test";
但是,这惨遭失败(不编译(:
error: no match for ‘operator=’ in ‘x = "test"’
尽管如此,如果我使用
x.foo("test");
它有效。我有兴趣了解它失败的原因,因为对我来说这两个函数是相同的。
谢谢。
您的Test
类包含一个隐式声明的复制赋值运算符(以及默认构造函数、复制构造函数和析构函数(。这将隐藏基类中的那个。为了将其视为重载,您必须使其在派生类中可访问:
class Test : public StringProperty {
public:
using StringProperty::operator=;
};
这是经典的。
operator=
是编译器为您创建的特殊方法之一(如果您不这样做(。因此,此自动创建的方法隐藏继承的方法。
您可以通过添加来解决它
using StringProperty::operator=;
行到类测试。
默认情况下,复制赋值和复制构造函数是为测试类生成的东西。
其他人已经通过详细的解释击败了我的解决方案,所以我将专注于其他事情。
我见过像这样的分层设计很快就会出现问题。我甚至与一位设计架构的高级开发人员合作,他甚至无法正确获得基本的数学向量库,因为他认为他可以创建一个向量基类,从中派生,向子类添加更多成员,并重用诸如从基类复制语义之类的东西(包括operator=(。可以说,他很快就遇到了切片等问题。我告诉他不要再试图以这种"扩展"的方式使用继承(子类建模看起来更像超类的东西(。像这样的问题为那些声称C++是一种糟糕的语言(例如:Linus Torvalds(的人火上浇油,因为很多人在使用它时会犯面向对象设计错误,尤其是在涉及继承时(我认为,另一个主要来源是单片类设计(。
通过基类提供给子类的赋值概念打破了多态性。想象一下,狗和猫从哺乳动物继承而来,它为两者提供了复制语义。当我们把狗复制到猫身上时会发生什么?假设我们调用某个接受哺乳动物的函数,并将Cat分配给它,但我们传入了对Dog的引用。应该发生什么?这在逻辑上是没有道理的。然而,如果 Dog 和 Cat 都使用 Mammal 的复制函数或运算符,编译器将允许这样做。
出于这个原因,我强烈建议您将基类设计为通常不可复制的,并研究虚拟克隆方法(原型模式(之类的东西,以避免这些类型的设计。基类通常需要适当且仔细地设计,以考虑多态性的基类。
值和多态性不能很好地协同工作。 症状你看到很容易修复:编译器提供的赋值运算符在派生类中隐藏基类中的任何赋值运算符。因此,您必须提供它的实现。 问题仍然存在,但是,您无法真正为其提供任何合理的语义:
Base* p1 = new Derived;
Base* p2 = new Base;
*p2 = *p1;
最后一行应该发生什么? 我希望在*p1 ==
*p2
之后,对平等进行一些适当的定义。 但部分*p1
的"值"是它具有动态类型Derived
。您无法这样做,因为您无法更改对象的类型它已经建成。
(可以制作行为多态的值类型,并且然而,通过信封的某种变体支持分配成语。 这是很多工作,通常非常缓慢,通常不值得它。
- 对静态分配的子类对象进行静态分配的纯虚拟父类引用是否合法?
- 为什么我只能在 4 GB 的虚拟内存空间上分配 2 GB?
- AWS pandas 安装出现错误:虚拟内存已耗尽:无法分配内存
- 为什么我不能拥有纯虚拟分配操作员?
- C++如何使用虚拟基类型声明全局静态分配的变量
- 如何使用一个 VirtualFree 调用删除多个相邻的虚拟内存分配?
- 虚拟函数"Shape"分配
- 为什么GCC警告使用STD ::元组和虚拟继承来调用非平凡的动作分配运算符
- 在虚拟内存中分配大型类C
- 虚拟分配操作员不允许static_cast
- 用于堆栈分配对象的C++虚拟析构函数内联
- 虚拟析构函数:如果基类动态分配内存,基类中是否需要它
- 混淆是指针和虚拟函数的内存分配
- 重新分配虚拟功能合法吗
- 从某个特定但很大的虚拟地址空间(例如,20GB以上)分配内存
- 如何清理已由虚拟成员函数分配的资源
- 如何从 ltrace 获取堆分配C++虚拟方法名称
- 警告:X的默认移动分配运算符将多次移动分配虚拟基类Y
- 虚拟分配
- 当虚拟基地移动分配操作符现在被允许使用时,它们会带来危险