C++语言解读三
今天说说继承.在C++中继承分共有继承,私有继承,多继承和单一继承,这点和C#不同,另外vritual关键字的用法也不相同,下面一一讲解
1:公有单一继承
#include<iostream>
using namespace std;
//公有单一继承 例子
class A
{
public:
void print1()const{cout<<"父类方法"<<endl;}
};
class B:public A
{
public:
void Print2()const{cout<<"子类方法"<<endl;}
};
int main()
{
B b;//栈中创建对象
b.print1();//父类方法
b.Print2();//自己的方法
return 0;
}
/*
程序说明
子类在公有继承父类后,父类的公有方法在子类中依然是公有方法
*/
using namespace std;
//公有单一继承 例子
class A
{
public:
void print1()const{cout<<"父类方法"<<endl;}
};
class B:public A
{
public:
void Print2()const{cout<<"子类方法"<<endl;}
};
int main()
{
B b;//栈中创建对象
b.print1();//父类方法
b.Print2();//自己的方法
return 0;
}
/*
程序说明
子类在公有继承父类后,父类的公有方法在子类中依然是公有方法
*/
2:公有多继承
#include<iostream>
using namespace std;
//公有多继承例子
class A
{
public:
void print1()const{cout<<"A类方法"<<endl;}
};
class B
{
public:
void Print2()const{cout<<"B类方法"<<endl;}
};
class C:public A,public B
{
public:
void Print3()const{cout<<"C类方法"<<endl;}
};
int main()
{
C c;
c.print1();//A方法
c.Print2();//B方法
c.Print3();//C方法
return 0;
}
using namespace std;
//公有多继承例子
class A
{
public:
void print1()const{cout<<"A类方法"<<endl;}
};
class B
{
public:
void Print2()const{cout<<"B类方法"<<endl;}
};
class C:public A,public B
{
public:
void Print3()const{cout<<"C类方法"<<endl;}
};
int main()
{
C c;
c.print1();//A方法
c.Print2();//B方法
c.Print3();//C方法
return 0;
}
3:多继承(有公有和私有一起)
#include<iostream>
using namespace std;
//多继承(有公有和私有一起)
class A
{
public:
void print1()const{cout<<"A类方法"<<endl;}
};
class B
{
public:
void Print2()const{cout<<"B类方法"<<endl;}
};
class C:public A,private B
{
public:
void Print3()const{cout<<"C类方法"<<endl;}
void Print4(){Print2();}
};
int main()
{
C c;
c.print1();//A方法
//c.Print2();//这里调用B类方法不能运行
c.Print3();//C方法
c.Print4();//这里调用B类方法
return 0;
}
/*
程序说明
1:私有继承用private关键字
2:私有继承有父类的公有方法在子类里就变成私有方法
3私有继承有父类的私有方法在子类里就变成不可访问
如需方法,就在子类里添加公有接口方法(就像程序里的Print4()方法一样来调用)
*/
using namespace std;
//多继承(有公有和私有一起)
class A
{
public:
void print1()const{cout<<"A类方法"<<endl;}
};
class B
{
public:
void Print2()const{cout<<"B类方法"<<endl;}
};
class C:public A,private B
{
public:
void Print3()const{cout<<"C类方法"<<endl;}
void Print4(){Print2();}
};
int main()
{
C c;
c.print1();//A方法
//c.Print2();//这里调用B类方法不能运行
c.Print3();//C方法
c.Print4();//这里调用B类方法
return 0;
}
/*
程序说明
1:私有继承用private关键字
2:私有继承有父类的公有方法在子类里就变成私有方法
3私有继承有父类的私有方法在子类里就变成不可访问
如需方法,就在子类里添加公有接口方法(就像程序里的Print4()方法一样来调用)
*/
4单一继承中的构造函数执行顺序
#include<iostream>
using namespace std;
//单一继承中的构造函数执行顺序
class A
{
public:
A(){cout<<"父类构造函数执行"<<endl;}
};
class B:public A
{
public:
B(){cout<<"子类构造函数执行"<<endl;}
};
int main()
{
B b;
return 0;
}
/*
程序说明
在创建子类后先构造它的父类的构造函数,然后在构造自己
*/
using namespace std;
//单一继承中的构造函数执行顺序
class A
{
public:
A(){cout<<"父类构造函数执行"<<endl;}
};
class B:public A
{
public:
B(){cout<<"子类构造函数执行"<<endl;}
};
int main()
{
B b;
return 0;
}
/*
程序说明
在创建子类后先构造它的父类的构造函数,然后在构造自己
*/
5多继承中的构造函数执行顺序
#include<iostream>
using namespace std;
//多继承中的构造函数执行顺序
class A
{
public:
A(){cout<<"A类构造函数执行"<<endl;}
};
class B
{
public:
B(){cout<<"B类构造函数执行"<<endl;}
};
class C
{
public:
C(){cout<<"C类构造函数执行"<<endl;}
};
class D:public A,public B,public C
{
public:
D(){cout<<"D类构造函数执行"<<endl;}
};
int main()
{
D d;
return 0;
}
/*
程序说明
在多继承中构造函数的执行顺序为第一个继承的先构造
这里将会先构造A,然后B,最后C
*/
using namespace std;
//多继承中的构造函数执行顺序
class A
{
public:
A(){cout<<"A类构造函数执行"<<endl;}
};
class B
{
public:
B(){cout<<"B类构造函数执行"<<endl;}
};
class C
{
public:
C(){cout<<"C类构造函数执行"<<endl;}
};
class D:public A,public B,public C
{
public:
D(){cout<<"D类构造函数执行"<<endl;}
};
int main()
{
D d;
return 0;
}
/*
程序说明
在多继承中构造函数的执行顺序为第一个继承的先构造
这里将会先构造A,然后B,最后C
*/
6继承中的析购函数执行顺序
#include<iostream>
using namespace std;
//继承中的析购函数执行顺序
class A
{
public:
A(){cout<<"A类构造函数执行"<<endl;}
~A(){cout<<"A类析购函数执行"<<endl;}
};
class B
{
public:
B(){cout<<"B类构造函数执行"<<endl;}
~B(){cout<<"B类析购函数执行"<<endl;}
};
class C
{
public:
C(){cout<<"C类构造函数执行"<<endl;}
~C(){cout<<"C类析购函数执行"<<endl;}
};
class D:public A,public B,public C
{
public:
D(){cout<<"D类构造函数执行"<<endl;}
~D(){cout<<"D类析购函数执行"<<endl;}
};
int main()
{
D d;
return 0;
}
/*
程序说明
在多继承中析购函数的执行顺序为先析购子类,然后一级一级的析购下去
*/
using namespace std;
//继承中的析购函数执行顺序
class A
{
public:
A(){cout<<"A类构造函数执行"<<endl;}
~A(){cout<<"A类析购函数执行"<<endl;}
};
class B
{
public:
B(){cout<<"B类构造函数执行"<<endl;}
~B(){cout<<"B类析购函数执行"<<endl;}
};
class C
{
public:
C(){cout<<"C类构造函数执行"<<endl;}
~C(){cout<<"C类析购函数执行"<<endl;}
};
class D:public A,public B,public C
{
public:
D(){cout<<"D类构造函数执行"<<endl;}
~D(){cout<<"D类析购函数执行"<<endl;}
};
int main()
{
D d;
return 0;
}
/*
程序说明
在多继承中析购函数的执行顺序为先析购子类,然后一级一级的析购下去
*/
7:多继承中出现的两义性,什么是两义性呢?请看代码
#include<iostream>
using namespace std;
class A
{
public:
void Print(){cout<<"类A方法"<<endl;}
};
class B:virtual public A
{
};
class C:virtual public A
{
};
class D:public B,public C
{
};
int main()
{
D d;
//d.Print();这里会出现ambiguous错误。
//编译器会提示这个Print是从类A继承的还是从类B继承的,它不明白
//下面是正确的调用
d.C::Print();//用类名加双冒号调用
return 0;
}
/*
程序说明
*/
using namespace std;
class A
{
public:
void Print(){cout<<"类A方法"<<endl;}
};
class B:virtual public A
{
};
class C:virtual public A
{
};
class D:public B,public C
{
};
int main()
{
D d;
//d.Print();这里会出现ambiguous错误。
//编译器会提示这个Print是从类A继承的还是从类B继承的,它不明白
//下面是正确的调用
d.C::Print();//用类名加双冒号调用
return 0;
}
/*
程序说明
*/
8:虚基类是不会产生两义性这个问题呢,那么怎么定义虚基类呢?请看代码
#include<iostream>
using namespace std;
//两义性
class A
{
public:
void Print(){cout<<"类A方法"<<endl;}
};
class B:virtual public A
{
};
class C:virtual public A
{
};
class D:public B,public C
{
};
int main()
{
D d;
d.Print();
return 0;
}
/*
程序说明
用virtual关键字定义虚基类
*/
using namespace std;
//两义性
class A
{
public:
void Print(){cout<<"类A方法"<<endl;}
};
class B:virtual public A
{
};
class C:virtual public A
{
};
class D:public B,public C
{
};
int main()
{
D d;
d.Print();
return 0;
}
/*
程序说明
用virtual关键字定义虚基类
*/
9:virtual关键字的使用
#include<iostream>
using namespace std;
//虚函数
class A
{
public:
virtual void Print(){cout<<"类A方法"<<endl;}
};
class B:virtual public A
{
public:
void Print(){cout<<"类B方法"<<endl;}
};
int main()
{
//定义指向类A指针
//指针多态
A* p=new A;
p->Print();//这里将访问类A方法
p=new B;
p->Print();//这里将会访问类B方法
//=-==============
//可能有些使用C#的程序员觉得这是必然的。
//这里如果我们不用指针,而转用对象,看看是什么情况
A a;
B b;
a.Print();
a=b;//注意这里将类B的一个对象赋予给类A的一个对象,再次调用a.Print()方法看看
a.Print();//这里还是会访问类A方法
return 0;
}
/*
程序说明
在动态联编情况下。如果程序实现多态必须用指针或引用,用对象是不可以的
*/
using namespace std;
//虚函数
class A
{
public:
virtual void Print(){cout<<"类A方法"<<endl;}
};
class B:virtual public A
{
public:
void Print(){cout<<"类B方法"<<endl;}
};
int main()
{
//定义指向类A指针
//指针多态
A* p=new A;
p->Print();//这里将访问类A方法
p=new B;
p->Print();//这里将会访问类B方法
//=-==============
//可能有些使用C#的程序员觉得这是必然的。
//这里如果我们不用指针,而转用对象,看看是什么情况
A a;
B b;
a.Print();
a=b;//注意这里将类B的一个对象赋予给类A的一个对象,再次调用a.Print()方法看看
a.Print();//这里还是会访问类A方法
return 0;
}
/*
程序说明
在动态联编情况下。如果程序实现多态必须用指针或引用,用对象是不可以的
*/
最后写一个小的程序来最终说明虚函数的使用
#include<iostream>
using namespace std;
class Language
{
public:
virtual void Print()
const
{
cout<<"程序默认使用语言为Java"<<endl;
}
};
class Cshop:public Language
{
void Print()
const
{
cout<<"程序使用C#语言编写"<<endl;
}
};
class Cpp:public Language
{
void Print()
const
{
cout<<"程序使用C++语言编写"<<endl;
}
};
class Dephi:public Language
{
void Print()
const
{
cout<<"程序使用Dephi语言编写"<<endl;
}
};
int main()
{
//定义个基类指针
Language* p;
Language* p1;
int con;
bool bl=true;//退出循环使用
while(true)
{
cout<<"<1>Cshop <2>Cpp <3>Dephi <0>quit";
cin>>con;
switch(con)
{
case 1:
p=new Cshop;
break;
case 2:
p=new Cpp;
break;
case 3:
p=new Dephi;
break;
case 0:
bl=false;
break;
default:
p=new Language;
break;
}
if(!bl){
//输入0情况下退出循环
break;
}
p1=p;
p1->Print();
}
return 0;
}
using namespace std;
class Language
{
public:
virtual void Print()
const
{
cout<<"程序默认使用语言为Java"<<endl;
}
};
class Cshop:public Language
{
void Print()
const
{
cout<<"程序使用C#语言编写"<<endl;
}
};
class Cpp:public Language
{
void Print()
const
{
cout<<"程序使用C++语言编写"<<endl;
}
};
class Dephi:public Language
{
void Print()
const
{
cout<<"程序使用Dephi语言编写"<<endl;
}
};
int main()
{
//定义个基类指针
Language* p;
Language* p1;
int con;
bool bl=true;//退出循环使用
while(true)
{
cout<<"<1>Cshop <2>Cpp <3>Dephi <0>quit";
cin>>con;
switch(con)
{
case 1:
p=new Cshop;
break;
case 2:
p=new Cpp;
break;
case 3:
p=new Dephi;
break;
case 0:
bl=false;
break;
default:
p=new Language;
break;
}
if(!bl){
//输入0情况下退出循环
break;
}
p1=p;
p1->Print();
}
return 0;
}