我有正在继承的复杂父类。现在,我只需要重写其少数几个函数,并希望以某种方式防止在子对象中调用父类的一些未重写的函数的可能性(这些父类的函数将无法正常工作)。我将在以后定义它们,如有必要,只是想弄清楚,目前它们不可用,但仍继承了一些使多态性成为可能的功能。有可能实现吗?还是我需要更改设计?
这是一个小例子:
class ParentClass
{
public:
virtual void write() { ... }
virtual void read() { ... }
virtual void calculate() { ... }
};
class ChildClass : public ParentClass
{
public:
void calculate() override { ... }
};
我想避免从read
对象调用write
或ChildClass
函数的可能性,因为这些函数定义起来很复杂,我现在不需要它们。但同时,我想防止某人在ChildClass
中使用父继承的函数。重要的是Parent class
是在第3方库中定义的,我无法更改父类。
我(笨拙的)想法是重写这些函数,并使其变得显而易见,以至于它们无法访问,但与正确的设计相距甚远……什么是正确的解决方案?
答案 0 :(得分:4)
一种方法,例如您想要使用一个类的一部分来实现一个新类,并且想要使用继承,但是您不想公开基类的整个API,而是使用私有继承,然后选择想转发。
这是一个例子:
#include <stdio.h>
class ParentClass
{
public:
virtual void write() { printf("write"); }
virtual void read() { printf("read"); }
virtual void calculate() { printf("calculate"); }
virtual void other() { printf("other"); }
};
class ChildClass : private ParentClass
{
public:
void calculate() override { printf("new calculate"); }
using ParentClass::other;
};
int main() {
ChildClass c;
c.calculate();
c.other();
}
在godbolt编译器资源管理器中,我得到了这个生成的程序集(如预期的那样)
.LC0:
.string "new calculate"
.LC1:
.string "other"
main:
sub rsp, 8
mov edi, OFFSET FLAT:.LC0
xor eax, eax
call printf
mov edi, OFFSET FLAT:.LC1
xor eax, eax
call printf
xor eax, eax
add rsp, 8
ret
using ParentClass::other
语法(用于从基类转发功能而不进行更改)仅是C ++ 11,没有标记功能c ++ 11,所以我不知道是否可以使用:),但是很方便
答案 1 :(得分:-2)
无需编写类似的代码,我目前无法尝试此解决方案,因此请花些盐。
我认为您可以在子类中将它们声明为deleted
,同时在基类中将它们保持虚拟。当您尝试在子类的对象上使用它时,这将提示编译时错误。也就是说,在子类中:
void write = deleted;
void read = deleted;
不幸的是,我不是100%确信这可以在虚函数上使用。如果不是这样,您还可以尝试从父类的那些函数中删除virtual
关键字,并在子类中使用上述已删除的函数进行纯重载,甚至可以声明它们而不定义它们(我更喜欢将已删除的函数定义为他们更明确)。同样,这将提示编译时错误。但是,您当然会失去多态的优势。
让我知道这些解决方案是否有效。