private,friend

private是在编译时刻检查的,也就是说如果能在编译时刻解决编译器对private的限制,那么private其实也是可以访问的(但是非常不建议这么做)。friend声明某个类,函数等是自己的friend,那么被声明的类,函数等就可以访问自己的私有变量啦。

private

首先我们来看测试程序:

《Effective C++》是本好书,接下来我写测试程序的时候尽量根据书中的准则来写。写在这里的一点就是尽量不要写没有参数的默认构造函数。

在我的测试例程里,我构建了A类,他有virtual的析构函数,拷贝构造函数和需要一个参数的构造函数。还有两个函数,一个传递的是A类的对象,一个传递的是A类的指针,函数都是尝试访问A类的对象的私有变量i。

在main函数的里面进行了测试,分别测试了f函数和g函数,通过输出来查看是否能正常输出,结果如下所示:

可以看到,这两个成员函数都访问到了private修饰的变量。

private对类来说,不同对象可以相互访问私有的成员变量。

friend

首先来看我的测试程序:

在A类里面我声明了A类的friend函数f函数,然后我尝试在f函数里面输出了A类的对象的私有变量。

结果如下所示:

friend修饰的函数是可以访问私有变量的,接下来我们来测试一下类是否可以,测试程序如下所示:

我设计了一个B类,将A类声明成了B类的友元类,然后在A类的成员函数里面访问B类的私有变量,我们来看一下输出结果:

可以看到,顺利输出了B类的私有变量。

注意下,单纯有前项声明的时候是只能用指针来声明访问的。

name hiding

name hiding是关于name hiding的知识,也就是名字隐藏,如果父类和子类中有相同的函数(相同指的是成员函数的名称和参数表相同)的时候,会发生什么事情呢?

测试

首先来看我们的测试程序:

可以看到我在父类A类里面定义了一个函数f,在子类B类里面也定义了一个函数f,这两个函数的名称相同,参数表也相同,那么这是,如果调用b.f()的话,程序会展示怎样的结果呢?

可以看到,程序只输出了B类里面的f函数,那么函数是如何继承下来的呢?

让我们来修改一下测试例程:

现在我修改了函数的返回值,看看这个时候是否能实现继承呢?结果如下所示:

可以看到,输出并没有发生改变,为什么呢?

我们单纯修改了函数的输出,对于编译器来说他并不知道届时谁会来接收这个函数的输出,因此并不能以此来界定函数的继承关系,让我们再来修改一下测试例程,修改一下子类中函数参数的数量:

这下总可以了吧,测试结果如下所示:

还是不行,此时并没有发生函数重载,反而还报了错误,说明还是不能通过这个方法来重载成员函数的。

破案了,原来要用多态或者域解析符来实现哦,测试例程如下所示:

测试结果如图所示:

终于正常啦~

课代表总结:

子类想要通过对象调用父类的成员函数,要么通过域解析符,要么通过virtual,也就是多态,还得是通过指针来进行调用。

测试例程:

#include <iostream>

using namespace std;

class A
{
    public:
        int a;
        A(int aa):a(aa){}
        virtual int f(int b){cout << "f in A " << endl;}
};

class B:public A
{
    public:
        int b;
        B(int bb):A(--b),b(++bb){}
        int f(int b,int b2){cout << "f in B " << endl;}
};

int main()
{
    A a(0);
    B b(2);
    A* pa = &b;
    pa->f(3);
    b.A::f(3);
    return 0;
}