我有一个关于概念的问题。首先,我是一名机械工程师,而不是程序员,因此我有一些C ++知识但没有太多经验。我使用有限元方法(FEM)来求解偏微分方程。
我有一个基类Solver
和两个子linSolver
,用于线性FEM,nlinSolver
用于非线性FEM。子女共享的成员和方法都在基类中。基类成员都是protected
。因此,使用继承使子类很容易使用",就像没有任何继承或其他边界一样。基类本身Solver
是不完整的,这意味着只有孩子对我有用。
这个概念实际上非常好 - 但我认为有一个无法使用的类是一个糟糕的设计。另外我读到protected
继承不是首选,如果可能应该避免。我认为最后一点并不适用于我的具体用途,因为我永远不会使用它,任何尝试都会失败(因为它不完整)。
问题是:
protected
继承真的很糟糕吗?感谢您的时间。 Dnaiel
答案 0 :(得分:3)
"无法使用"基类实际上很常见。您可以使用基类来定义继承基类的类可用的公共接口。如果你声明那些接口函数virtual
,你可以使用例如将调用对基类的引用或指针以及继承的类对象中的正确函数。
像这样:
class Base
{
public:
virtual ~Base() {}
virtual void someFunction() = 0; // Declares an abstract function
};
class ChildA : public Base
{
public:
void someFunction() { /* implementation here */ }
};
class ChildB : public Base
{
public:
void someFunction() { /* other implementation here */ }
};
使用上述课程,您可以
Base* ptr1 = new ChildA;
Base* ptr2 = new ChildB;
ptr1->someFunction(); // Calls `ChildA::someFunction`
ptr2->someFunction(); // Calls `ChildB::someFunction`
然而,这不起作用:
Base baseObject; // Compilation error! Base class is "unusable" by itself
虽然上面的(工作)示例很简单,但请考虑将指针传递给函数时可以执行的操作。您可以使用单个函数来获取指向基类的指针,而不是让两个重载函数各自使用实际类,而编译器和运行时系统将确保调用正确的(虚拟)函数:
void aGlobalFunction(Base* ptr)
{
// Will call either `ChildA::someFunction` or `ChildB::someFunction`
// depending on which pointer is passed as argument
ptr->someFunction();
}
...
aGlobalFunction(ptr1);
aGlobalFunction(ptr2);
即使基类是“无法使用的”#34;直接地,它仍然提供了一些功能,这些功能是C ++可以(和)使用的核心部分。
当然,基类不必是所有接口,它可以包含其他常用(protected
)辅助函数或实用函数,可以从继承基类的所有类中使用。请记住,继承是一个" is-a"班级之间的关系。如果你有两个不同的类,那么"是-a"什么,然后使用继承可能是一个非常好的解决方案。
答案 1 :(得分:2)
您应该检查Abstract class的概念。 它旨在提供无法实例化的基类。 为此,您在基类中提供至少一个方法,如此
virtual void f()=0;
每个子节点都必须覆盖f函数(或基类中的任何纯虚函数)才能实例化。
答案 2 :(得分:0)
不要将BaseClass视为一个类本身,而是作为接口契约和一些实现帮助。因此,它应该是抽象的,如果需要,通过声明dtor纯虚拟但无论如何提供实现。一些OO纯粹主义者可能会对任何非私人元素不满,但纯度不是一个好目标。