Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 派生类中的私有重写虚拟函数_C++_Inheritance_Virtual Functions_Private Members_Access Specifier - Fatal编程技术网

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