Bootstrap

一个类作为另一个类的数据成员

写程序的时候希望一个类能够访问另一个类的数据成员(protected, private),例如类A要访问类B中的数据成员。

1.保持封装性

可以通过在被访问的类(B)中定义访问权限为public的函数,用来返回数据成员的引用。

2.继承

当一个派生类从父类继承时,父类的所有成员就成为子类的成员,因此可以将被访问类作为父类被继承。要注意此时对父类成员的访问状态由继承时使用的继承限定符决定。

父类权限  继承方式
privateprotectedpublic
privateprivate    privateprivate
protectedprivate  protectedprotected
publicprivateprotectedpublic

3.友元

申明要访问类为被访问类的友元。例如类A要访问类B中的数据成员,在B的构造函数加上friend class A; 声明A是B的友元,可以直接访问到B中的所有成员。举个例子就是:

class B
{
private:
    int age;
protected:
    int money;
public:
    int gender;

    B()
    {
        age = 20;
        money = 1000;
        gender = 1;
    }

    friend class C;

    int getAge(){ 
        return age;    }
    int getMoney(){
        return money;
    }
    int getGender(){
        return gender;
    }

};

class A
{
public :
    A() {};

    int compute(D &testd)
    {
        return ( 25 - testd.age) * testd.money  ;
    }
};

int main()
{
    A testa;
    B testb;
    testa.compute(testa); /* 输出结果为(25-20)*1000 */
}

此时B的一个对象作为A某函数成员的形参,原本通过对象是无法访问到B中的private和protected成员。还可以声明B作为A的数据成员,这样也能访问到B中所有成员。
当使用后一种方法,一个类作为另一个类的数据成员。需要注意:

如果一个类B的对象作为另一个类A的数据成员,则在类A的对象创建过程中,调用其构造函数的过程中,数据成员(类B的对象)会自动调用类B的构造函数。 但应注意:如果类B的构造函数为有参函数时,则在程序中必须在类A的构造函数的括号后面加一“:”和被调用的类B的构造函数,且调用类B的构造函数时的实参值必须来自类A的形参表中的形参。这种方法称为初始化表的方式调用构造函数。

如:以上面定义的类A为例,在对类A的对象进行初始化时,必须首先初始化其中的子对象,即必须首先调用这些子对象的构造函数。因此,类A的构造函数的定义格式应为:

A:: A(参数表0):成员1(参数表1),成员2(参数表2),…,成员n(参数表n) { ……}

其中,参数表1提供初始化成员1所需的参数,参数表2提供初始化成员2所需的参数,依此类推。并且这几个参数表的中的参数均来自参数表0,另外,初始化X的非对象成员所需的参数,也由参数表0提供。

在构造新类的对象过程中,系统首先调用其子对象的构造函数,初始化子对象;然后才执行类X自己的构造函数,初始化类中的非对象成员。对于同一类中的不同子对象,系统按照它们在类中的说明顺序调用相应的构造函数进行初始化,而不是按照初始化表的顺序。

 

另外:访问的时候还有几个前提条件

1.被引用的变量所在类必须被完整地定义,而不是只有前向声明(例如只是一行class A;);

2.被引用的变量必须是引用处可以访问的。

  2.1.访问变量的语句所在的类被声明为被访问的变量所在类的友元类;

  2.2.访问变量的语句所在的函数被声明为被访问变量所在类的友元函数;

  2.3.被访问变量被public修饰,且访问变量的语句所在的类不是被访问变量所在的类的private继承派生类;

  2.4.被访问变量被protected修饰,且访问变量的语句所在的类是被访问变量所在的类的public继承派生类;

  2.5.访问变量的语句所在的类定义在被访问变量所在的类的内部。

现在假设满足以上前提条件的A类的某个成员函数或成员初始化的语句要引用B类的成员m,

那么

1.当m是A类的静态成员时,可以通过A::m引用;

2.当m是A类的非静态成员,且对象a是类A的实例时,可以通过a.m引用。

以上基本包含了所有的情况。

转载于:https://www.cnblogs.com/summerRQ/articles/2480578.html

;