不允许切片以保持多个父类属性同步
Disallow slicing to keep multiple parent class properties in sync
我从两个父类派生一个对象。这两个父母都有不同类型的属性,但我希望孩子能让他们保持同步。然而,我想禁止库的用户通过切片意外地将Child
视为ParentA
或ParentB
。例如:
#include <iostream>
class ParentA
{
public:
void modify()
{
std::cout << "modifyA" << std::endl;
}
void readA()
{
std::cout << "readA" << std::endl;
}
};
class ParentB
{
public:
void modify()
{
std::cout << "modifyB" << std::endl;
}
void readB()
{
std::cout << "readB" << std::endl;
}
};
class Child : public ParentA, public ParentB
{
public:
void modify()
{
// Do some bounds checking to make sure ParentA and ParentB stay in sync, then:
ParentA::modify();
ParentB::modify();
std::cout << "modifyChild" << std::endl;
}
};
void Change(ParentA object)
{
object.modify();
}
int main()
{
std::cout << "This is standard:" << std::endl;
ParentA parentA;
parentA.modify();
ParentB parentB;
parentB.modify();
Child child;
child.readA();
child.readB();
child.modify();
std::cout << "Want to avoid this:" << std::endl;
Change(child);
return 0;
}
此对Change(child);
的调用调用ParentA
的modify()
函数,其中ParentA
属性可能与ParentB
属性不同步,从而使Child
处于坏状态。
ParentA
和ParentB
中有很多函数(这里是read*()
),我不想手动从Child
转发,所以我不能私下推导。
有没有办法使对Change(child)
的调用产生编译器错误(而不更改Change
的签名)?
实际上有一种方法可以做到这一点(尽管说你不喜欢):private
或protected
继承是实现你想要的东西的C++机制。
请记住,由于您的子类试图在A和B之间保持某种不变量,如果您继承public
ly,则无论如何都会有人找到使用A或B的接口来违反不变量的方法,因此您需要保护这些接口不受直接在子类中使用的影响,而限制继承完全做到了这一点。
如果父类中有一些方法不影响两个类不变量,那么可以将它们using
放到Child的公共部分中。
正如注释所说,最干净的方法可能是用private
从ParentA
和ParentB
继承并转发所需的函数。
我有另一个想法:可以将ParentA
和ParentB
的功能提取到两个抽象类(AbstractParentA
、AbstractParentB
)中,并将这些类用作基类。
这会给你想要的行为:
#include <iostream>
class AbstractParentA
{
virtual void no_instance() = 0;
public:
void modify()
{
std::cout << "modifyA" << std::endl;
}
void readA()
{
std::cout << "readA" << std::endl;
}
};
class AbstractParentB
{
virtual void no_instance() = 0;
public:
void modify()
{
std::cout << "modifyB" << std::endl;
}
void readB()
{
std::cout << "readB" << std::endl;
}
};
class ParentA : public AbstractParentA
{
virtual void no_instance() override {}
};
class ParentB : public AbstractParentB
{
virtual void no_instance() override {}
};
class Child : public AbstractParentA, public AbstractParentB
{
virtual void no_instance() override {}
public:
void modify()
{
// Do some bounds checking to make sure ParentA and ParentB stay in sync, then:
AbstractParentA::modify();
AbstractParentB::modify();
std::cout << "modifyChild" << std::endl;
}
};
void Change(ParentA object)
{
object.modify();
}
int main()
{
std::cout << "This is standard:" << std::endl;
ParentA parentA;
parentA.modify();
ParentB parentB;
parentB.modify();
Child child;
child.readA();
child.readB();
child.modify();
std::cout << "Want to avoid this:" << std::endl;
Change(child);
return 0;
}
错误C2664:"void Change(ParentA)":无法从"Child"转换参数1
注意:没有用户定义的转换运算符可以执行此转换,或者该运算符不能称为
- 从类继承时,继承的类是否会通过父类重新定义继承的变量
- 从父类方法返回子类对象
- c++, 在子类中,如何在没有对象的情况下访问父类的方法?
- 将父类对象强制转换为子类的问题
- C++删除未使用的类属性会导致 std::logic_error
- 在运行时选择父类的实现
- 如何在C++子类中访问父类的私有变量
- 将父类的子类的数据复制到具有相同父类的另一个类
- 父类的私有函数会导致对具有相同名称和相似参数的子类中的公共函数的不明确调用
- C++ 将子类的对象添加到父类的向量中
- 两个父类的构造函数的序列
- 如何从传递到对象的对象内部访问对象的类属性?
- 为什么我的子类不继承父类的字符串?
- C++调用使用重写函数的父类函数
- 在父类中公开受保护的构造函数
- 不允许切片以保持多个父类属性同步
- 如果我希望子类向父类添加功能,我是否应该保护我的属性
- 从父类访问子类属性
- 在子类中定义一个属性,然后在父类中使用它,这在PHP中是一种奇怪的行为
- 使用具有相同名称和属性的父类函数