您的位置:首页 > 编程语言 > C语言/C++

c++primer——面向对象编程

2015-10-15 20:11 465 查看
1.重构现象:因为派生类的构造函数只能初始化它的直接基类,所以这样就出现了一种新的现象——重构,重构是很常见的,它是指在子类中重新定义父类的构造函数,已达到自己想要的构造函数。重构要注意的是一旦被重构,编译器必须重新编译这些类的代码。

class pp
{
public:
pp()
{
a=0;
cout<<a;
}
pp(int x,int y,int z)
{
a=x,b=y,c=z;
cout<<a<<b<<c;
}
void test1(int i);
protected:
int a;
int b;
int c;

};

class aa :public pp
{
public:
aa(){}
aa(int x,int y,int z):pp(x,y,z)//调用基类的哪个构造函数
{

{
a=x,b=y,c=2*z;//重构现象(一定是先调用基类的构造函数,然后在自己重构自己的函数)
int d=a+b+c;
cout<<d;

}

}
};
2.友元和继承

友元提供了不同类的成员函数之间、类的成员函数与一般函数之间进行数据共享的机制。友元关系不能传递和继承。

友元函数是可以直接访问类的私有成员的非成员函数。它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字friend,其格式如下: 

friend 类型 函数名(形式参数);
    友元函数的声明可以放在类的私有部分,也可以放在公有部分,它们是没有区别的,都说明是该类的一个友元函数。

      一个函数可以是多个类的友元函数,只需要在各个类中分别声明。

      友元函数的调用与一般函数的调用方式和原理一致。

友元类的申明只对申明对象有效,对申明对象的基类和子类是无效的。友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。        当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。定义友元类的语句格式如下:
friend class 类名; 其中:friend和class是关键字,类名必须是程序中的一个已定义过的类。

使用友元类时注意:

(1) 友元关系不能被继承。

 (2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。

 (3) 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明


突然想到之前的一个知识点:struct和class的唯一区别是类的成员的默认保护级别,在struct的默认是public,而class的默认情况下是private的。

3.虚函数和作用域

<span style="font-family:微软雅黑;">class  base
{
public:
virtual int fun();
};
class D1:public base
{
public:
int fun(int );//这个并没有覆盖原来的fun()
virtual void f2();
};
class D2:public D1
{
public:
int fun(int);
int fun();
void f2();

};
/*</span><span style="font-family: 微软雅黑;">*/</span>
<span style="font-family:微软雅黑;">

int main()
{

base b1;
D1 d1;
D2 d2;
base *bp1=&b1,*bp2=&d1,*bp3=&d2;//转化成基类
bp1->fun();//base::fun()
bp2->fun();//base::fun()
bp3->fun();//d2::fun()
D1 *dp1=&d1;
D2 *dp2=&d2;
bp2->f2();//错误:base中没有f2的成员
dp1->f2();//d1::f2()
dp2->f2();//d2::f2()

return 0;

}</span>
4.虚析构函数:(一般基类的析构函数需要用虚函数)下例:



<pre name="code" class="cpp">class ClxBase
{
public:
ClxBase() {};
virtual ~ClxBase() {};
virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};

class ClxDerived : public ClxBase
{
public:
ClxDerived() {};
~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };

void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };
};



<span style="font-family: Arial; font-size: 14px; line-height: 26px; background-color: rgb(230, 230, 230);">主函数:</span><pre name="code" class="cpp">ClxBase *pTest = new ClxDerived;//定义的是基类,这个跟基类是否是虚函数有很大关系
<pre name="code" class="cpp">ClxDerived *p=new <span style="font-family: Arial;">ClxDerived;//定义是派生类</span>
pTest->DoSomething();delete pTest;
delete p;//无论基类是否是虚函数都会从派生类开始调用





5.构造和析构的调用顺序:下例:

class base
{
public:
base()
{
cout<<"base_c"<<endl;
}

~base()
{
cout<<"base_d"<<endl;
}
virtual int fun(){return 0;};
};
class D1:public base
{
public:
D1()
{
cout<<"d1_c"<<endl;
}
~D1()
{
cout<<"d1_d"<<endl;
}
int fun(int ){return 0;};
virtual void f2(){};
};
class D2:public D1
{
public:
D2()
{
cout<<"d2_c"<<endl;
}
~D2()
{
cout<<"d2_d"<<endl;
}
int fun(int){return 0;};
int fun(){return 0;};
void f2(){};

};

int main()
{

base b1;
D1 d1;
D2 d2;
base *bp1=&b1,*bp2=&d1,*bp3=&d2;//转化成基类
bp1->fun();
bp2->fun();
bp3->fun();
D1 *dp1=&d1;
D2 *dp2=&d2;
dp1->f2();
dp2->f2();
return 0;

}
输出结果:

base_c

base_c

d1_c

base_c

d1_c

d2_c

d2_d

d1_d

base_d

d1_d

base_d

base_d

无论是多少级继承,构造函数总是先从基类开始,而析构函数就是先从本身开始到基类。





内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: