如何使继承的虚函数不可用?
How to make an inherited virtual function not usable?
我有一个抽象基础 class,它声明了一个纯虚函数 (virtual method() = 0;
)。一些继承的 classes 专门研究并使用此方法,但有一个继承的 classes 我不想让此方法可用。我该怎么做?将其设为私有是唯一的选择吗?
Is making it private the only choice?
不,这根本不是一个选择,因为如果它是基础 classes 中的 public
或 protected
,您仍然可以访问该方法。
除了在 class 中实施该方法并求助于 运行 次失败之外,您无能为力。您 可以 将整个东西移植到模板并使用 静态多态性 ,进一步狡猾,您可以设计一个 编译时间 在某些情况下会失败,但这可能是设计矫枉过正。
我想你可以把它变成一个普通的虚函数,而不是像这样的纯虚函数:
virtual void method() { /* code */ }
如果此函数未在另一个 class 中使用,您将能够捕捉到它。例如你可以警告自己:
virtual void method() { error = true; } //or whatever
好吧,你可以抛出它,这将使定位更容易。
void method() override { throw /* whatever */ ; }
动态多态是一个运行时属性。因此出现运行时错误。如果你照顾一些会在编译时触发的东西,你需要静态多态性。
template<typename Child>
struct Parent {
void callMe() {
static_cast<Child*>(this)->callMeImpl();
}
};
struct SomeChild : Parent<SomeChild> {
};
现在,如果您尝试从 SomeChild
扩展的父级调用 callMe
,将出现编译时错误。
你也可以像动态多态一样持有指向父函数的指针,因为父函数会调用子函数
正如其他人所说,无法在编译时强制执行此操作。如果您指的是指向基 class 的指针,则编译器无法知道该指针是否指的是 派生的 classes 之一] 实施此方法或 不 .
的方法
所以这个案例必须在运行时处理。一种选择是只抛出异常。另一种选择是引入一个间接级别,这样您就可以在调用之前询问您的基 class 是否实现了某个功能。
假设您有一个 Base
class 具有三种方法 foo
、bar
和 doit
并且一些派生的 class 没有想要实现 foo
那么你可以将 Base
class 分成两个基础 classes:
class Base1 {
public:
virtual void foo() = 0;
};
class Base2 {
public:
virtual void bar() = 0;
virtual void doit() = 0;
};
然后在您当前使用 Base
的地方改用 BaseSource
:
class BaseSource {
public:
virtual Base1* getBase1() = 0;
virtual Base2* getBase2() = 0;
};
其中 getBase1
和 getBase2
可以 return nullptr
如果 BaseSource
不提供该接口:
class Derived : public BaseSource, public Base2 {
public:
// don't implement foo();
// Implemementation of Base2
void bar() override;
void doit() override;
Base1* getBase1() override { return nullptr; } // Doesn't implement Base1
Base2* getBase2() override { return this; }
};
int main() {
std::vector<std::unique_ptr<BaseSource>> objects;
objects.push_back(std::make_unique<Derived>());
for (auto& o : objects) {
auto b1 = o->getBase1();
if (b1)
b1->foo();
auto b2 = o->getBase2();
if (b2)
b2->bar();
}
}
我有一个抽象基础 class,它声明了一个纯虚函数 (virtual method() = 0;
)。一些继承的 classes 专门研究并使用此方法,但有一个继承的 classes 我不想让此方法可用。我该怎么做?将其设为私有是唯一的选择吗?
Is making it private the only choice?
不,这根本不是一个选择,因为如果它是基础 classes 中的 public
或 protected
,您仍然可以访问该方法。
除了在 class 中实施该方法并求助于 运行 次失败之外,您无能为力。您 可以 将整个东西移植到模板并使用 静态多态性 ,进一步狡猾,您可以设计一个 编译时间 在某些情况下会失败,但这可能是设计矫枉过正。
我想你可以把它变成一个普通的虚函数,而不是像这样的纯虚函数:
virtual void method() { /* code */ }
如果此函数未在另一个 class 中使用,您将能够捕捉到它。例如你可以警告自己:
virtual void method() { error = true; } //or whatever
好吧,你可以抛出它,这将使定位更容易。
void method() override { throw /* whatever */ ; }
动态多态是一个运行时属性。因此出现运行时错误。如果你照顾一些会在编译时触发的东西,你需要静态多态性。
template<typename Child>
struct Parent {
void callMe() {
static_cast<Child*>(this)->callMeImpl();
}
};
struct SomeChild : Parent<SomeChild> {
};
现在,如果您尝试从 SomeChild
扩展的父级调用 callMe
,将出现编译时错误。
你也可以像动态多态一样持有指向父函数的指针,因为父函数会调用子函数
正如其他人所说,无法在编译时强制执行此操作。如果您指的是指向基 class 的指针,则编译器无法知道该指针是否指的是 派生的 classes 之一] 实施此方法或 不 .
的方法所以这个案例必须在运行时处理。一种选择是只抛出异常。另一种选择是引入一个间接级别,这样您就可以在调用之前询问您的基 class 是否实现了某个功能。
假设您有一个 Base
class 具有三种方法 foo
、bar
和 doit
并且一些派生的 class 没有想要实现 foo
那么你可以将 Base
class 分成两个基础 classes:
class Base1 {
public:
virtual void foo() = 0;
};
class Base2 {
public:
virtual void bar() = 0;
virtual void doit() = 0;
};
然后在您当前使用 Base
的地方改用 BaseSource
:
class BaseSource {
public:
virtual Base1* getBase1() = 0;
virtual Base2* getBase2() = 0;
};
其中 getBase1
和 getBase2
可以 return nullptr
如果 BaseSource
不提供该接口:
class Derived : public BaseSource, public Base2 {
public:
// don't implement foo();
// Implemementation of Base2
void bar() override;
void doit() override;
Base1* getBase1() override { return nullptr; } // Doesn't implement Base1
Base2* getBase2() override { return this; }
};
int main() {
std::vector<std::unique_ptr<BaseSource>> objects;
objects.push_back(std::make_unique<Derived>());
for (auto& o : objects) {
auto b1 = o->getBase1();
if (b1)
b1->foo();
auto b2 = o->getBase2();
if (b2)
b2->bar();
}
}