C++ 派生类中的私有重写虚拟函数
如果虚拟成员函数在基类中是公共的,那么将从基类重写的虚拟成员函数设置为私有有什么意义吗C++ 派生类中的私有重写虚拟函数,c++,inheritance,virtual-functions,private-members,access-specifier,C++,Inheritance,Virtual Functions,Private Members,Access Specifier,如果虚拟成员函数在基类中是公共的,那么将从基类重写的虚拟成员函数设置为私有有什么意义吗 struct base { virtual void a(); }; struct derived : base { // ... private: void a() override; }; 对于非虚方法,同样的推理也适用:如果类本身应该调用它,则将其设置为私有 考虑一下: 也许a和b应该受到保护,但无论如何派生的可以改变可访问性,它需要一些文档,以便派生的知道如何实现a和b查看您的设计
struct base {
virtual void a();
};
struct derived : base {
// ...
private:
void a() override;
};
对于非虚方法,同样的推理也适用:如果类本身应该调用它,则将其设置为私有 考虑一下:
也许
a
和b
应该受到保护
,但无论如何派生的
可以改变可访问性,它需要一些文档,以便派生的
知道如何实现a
和b
查看您的设计,我发现不能直接调用derived::a
,只能通过base
接口
有什么意义吗?考虑到,一旦我们有了<代码>派生<代码>实例,我们总是可以向上转换到它的基,所以给出
derived d;
虽然d.a()
base & b = d;
b.a(); //which actually calls derived::a
换句话说:derived::a
毕竟不是私有的,我不鼓励这种设计,因为它可能会让用户感到困惑
如果derived
中的private成员在base
中也是private成员,情况就会发生变化:这次很明显,它们不能直接在base
或derived
之外调用
假设我们有两个函数,并希望根据作为参数传递给第三个函数的值有条件地调用它们:
struct base
{
void dosomething(bool x)
{
if(x)
{
do_this();
}
else
{
do_that();
}
}
private:
virtual void do_this(){}
virtual void do_that(){}
};
因此,派生类可能类似于:
struct derived : base
{
private:
void do_this() override { }
void do_that() override { }
};
没有其他类可以调用它们,除非它扩展了base
本身:
derived d;
d.dosomething(true); //will call do_this() in derived
d.dosomething(false); //will call do_that() in derived
d.do_that() //won't compile
是,如果将基类作为私有继承。否则,它更像是一种奇怪的显式限制——用户必须进行显式转换才能使用该函数——这通常是不明智的,因为很少有人能够理解作者的意图
如果要限制基类中的某些函数,请进行私有/受保护继承,并通过使用
关键字声明要在派生类中保护/公开的基类方法。如果您被迫在实现类上执行两阶段构造(即拥有init()
方法以及或代替必须调用的构造函数(我知道,但有原因),则在将实例指针作为接口指针传回之前,您将停止直接调用实例指针上的任何/other/方法。再多做一点,将继承设置为私有,并让您的一个公共init函数返回接口指针
另一个原因是您不/不需要/在最终的实现类声明中编写public:
,因此默认情况下,所有内容都是私有的。但为什么要这样做,并使用struct而不是class呢?我不知道。也许这是由于样式战在某个时候从类转换而来的?类和类之间没有区别
和struct
而不是默认值access@formerlyknownas_463035818确实如此。因此,如果您有一个实现类,它可以全部是默认的private
,因为没有一个方法将被直接调用。然后发生的是一些style warrior出现并说“这应该是一个结构,因为‘blah是一个wotsit’”,这是一条在这个圈子之外没有任何意义的规则,初级程序员将其更改为struct(因为风格战士只会在会/真的/激怒原作者的情况下自己更改内容)并将private:
放入,使其行为相同,因为没有人想重新测试它。然后您就有了操作代码。我宁愿编写一个始终返回完全初始化对象的工厂,也不愿这样做。如果需要,您可以使用标记类仅允许工厂创建对象。为什么不声明模板方法ivate在基类中?这表示这些是类内部使用的方法。@Jens我以此为前提。我必须承认我的示例不太令人信服
derived d;
d.dosomething(true); //will call do_this() in derived
d.dosomething(false); //will call do_that() in derived
d.do_that() //won't compile