类的定义一般包括两部分,一是类的属性,二是他所拥有的方法。类的实例化是指给类的加载并初始化过程,比如一个people类,我们具体到每一个人就是类的实例化,此外一个类可以在此类上进行扩展。比如people类,我们分为 外国people 和 中国people,那么people叫做基类,外国people叫做派生类或子类
1.C++类的定义
C++使用class关键字定义一个类:
public:公共的行为或属性(类外可以调用);
private:表示该部分内容是私密的,不能被外部访问或调用,只能在类内调用;
protected:保护成员,和私有成员类似,不过在派生类可以调用;
比如我们建立一个people类
#include <iostream>
using namespace std;
class people{
public:
void a(){
cout<<name;
}
private:
string name="小明";
void b(){
cout<<"dsfsfds"; //不必在意;
}
};
int main(){
people cao; //实例化
cao.a();
return 0;
}
类的传参,比如我们要传入人的身高和体重,可以通过一个函数传入,传给私有变量;
#include <iostream>
using namespace std;
class people{
public:
void a(){
cout<<name<<' '<<height<<' '<<weight;
}
void chuanru(int x,int y){
//x,y是函数内的的变量,因此需要赋值给整个类的变量,作用域不同
height=x;
weight=y;
}
private:
string name="小明";
int height;
int weight;
};
int main(){
people cao;
cao.chuanru(170,130);
cao.a();
return 0;
}
此外类内的函数或者方法可以放到类外面,需要先在类内声明函数,通过“::”作用域操作符实现例如:
#include <iostream>
using namespace std;
class people{
public:
void a();
void chuanru(int x,int y); //函数声明
private:
string name="小明";
int height;
int weight;
};
void people::a(){ //表面是people的a函数
cout<<name<<' '<<height<<' '<<weight;
}
void people::chuanru(int x,int y){
height=x;
weight=y;
}
int main(){
people cao;
cao.chuanru(170,130);
cao.a();
return 0;
}
2.初识构造函数和析构函数
先不管那些拷贝构造函数和转换构造函数,我们先学习普通的,
#include <iostream>
using namespace std;
class people{
public:
people(int x=8,int y=9){ //构造函数,可以设置默认值
height=x;
weight=y;
}
void a(){
cout<<name<<' '<<height<<' '<<weight;
}
private:
string name="小明";
int height;
int weight;
};
int main(){
people cao(170,130); //构造函数传参,
cao.a();
return 0;
}
同理构造函数也可以放到类外面
#include <iostream>
using namespace std;
class people{
public:
people(int x,int y);
void a();
private:
string name="小明";
int height;
int weight;
};
people::people(int x=9,int y=8){ //类内或类外只能有一个地方初始化
height=x;
weight=y;
}
void people::a(){
cout<<name<<' '<<height<<' '<<weight;
}
int main(){
people cao(170,130);
cao.a();
return 0;
}
构造函数用来初始化类,析构函数与构造函数相反;在对象生命周期结束后自动调用,用于在对象删除之前的清理工作,清理对象释放内存;
#include <iostream>
using namespace std;
class people{
public:
people(int x,int y);
void a();
~people();
private:
string name="小明";
int height;
int weight;
};
people::people(int x=9,int y=8){
height=x;
weight=y;
}
people::~people(){
}
void people::a(){
cout<<name<<' '<<height<<' '<<weight;
}
int main(){
people cao(170,130);
cao.a();
return 0;
}
是生命周期结束,举个例子:
#include <iostream>
using namespace std;
class people{
public:
people(string n,int x,int y);
void a();
~people();
private:
string name;
int height;
int weight;
};
people::people(string n,int x=9,int y=8){
name=n;
height=x;
weight=y;
cout<<name<<' '<<"调用构造函数"<<endl;
}
people::~people(){
cout<<name<<' '<<"调用析构函数"<<endl;
}
void people::a(){
cout<<name<<' '<<height<<' '<<weight<<endl;;
}
void shiyan(){
people lin("小刚",180,190);
}
int main(){
people cao("小明",170,130);
shiyan();
cout<<"main还没结束!"<<endl;
return 0;
}
小明是在main函数内,小刚是在shiyan()函数内,调用完shiyan() 函数后小刚生命周期结束,调用小刚的析构函数,而小明是等到main函数结束后调用析构函数;
其实构造函数还有初始化列表形式:
#include <iostream>
using namespace std;
class people{
public:
people(int x,int y); //构造函数
void a();
~people(); //析构函数
private:
string name="小明";
int height;
int weight;
};
people::people(int x=9,int y=8):height(x),weight(y){} //初始化列表
people::~people(){
}
void people::a(){
cout<<name<<' '<<height<<' '<<weight;
}
int main(){
people cao(170,130);
cao.a();
return 0;
}
想知道构造函数怎样工作的吗?
我来告诉你
首先我们来看定义未知数的顺序;
我们先定义height,在定义weight,那么构造函数是按照先初始化height在初始化weight的顺序构造的,并不是按照构造函数的顺序,举个例子:
#include <iostream>
using namespace std;
class people{
public:
people(int x);
void a();
~people();
private:
string name="小明";
int height;
int weight;
};
people::people(int x=9):height(x),weight(height){}
//先初始化height,再将height赋值给weight
people::~people(){
}
void people::a(){
cout<<name<<' '<<height<<' '<<weight;
}
int main(){
people cao(170);
cao.a();
return 0;
}
#include <iostream>
using namespace std;
class people{
public:
people(int x);
void a();
~people();
private:
string name="小明";
int height;
int weight;
};
people::people(int x=9):height(weight),weight(x){}
//先初始化height,但height依赖于weight,由于weight没有初始化,所以出现错误;
people::~people(){
}
void people::a(){
cout<<name<<' '<<height<<' '<<weight;
}
int main(){
people cao(170);
cao.a();
return 0;
}
3.类的继承
子承父业吗,子类继承父类,分为三种继承方式;
(1)公共继承:父类的公共属性在子类还是公共属性,保护属性还是保护属性,私有属性子类访 问不到
(2)保护继承:父类的公共属性和保护属性在子类中都变为保护属性;私有还是访问不到
(3)私有继承:父类的公共属性在子类变为保护属性,父类的保护属性变为私有属性,私有访问 不到;
举例说明:
(1)公共继承:
#include <iostream>
using namespace std;
class father{
public:
string a="father 公共";
protected:
string b="father 保护";
private:
string c="father 私有";
};
class son:public father{
public:
// string a="son 公共";
// string b="son 保护";
// c="son 私有";
void dain(){
cout<<a<<endl<<b<<endl<<endl;
// cout<<c; //报错
}
};
int main(){
son linyuan;
linyuan.dain();
cout<<linyuan.a<<endl;
// cout<<linyuan.b<<endl; //报错
return 0;
}
(2)保护继承
#include <iostream>
using namespace std;
class father{
public:
string a="father 公共";
protected:
string b="father 保护";
private:
string c="father 私有";
};
class son:protected father{
public:
// string a="son 公共";
// string b="son 保护";
// c="son 私有";
void dain(){
cout<<a<<endl<<b<<endl<<endl;
// cout<<c; //报错
}
};
int main(){
son linyuan;
linyuan.dain();
// cout<<linyuan.a<<endl;
// cout<<linyuan.b<<endl; //报错
return 0;
}
(3)私有继承
#include <iostream>
using namespace std;
class father{
public:
string a="father 公共";
protected:
string b="father 保护";
private:
string c="father 私有";
};
class son:private father{
public:
// string a="son 公共";
// string b="son 保护";
// c="son 私有";
void dain(){
cout<<a<<endl<<b<<endl<<endl;
// cout<<c; //报错
}
};
int main(){
son linyuan;
linyuan.dain();
// cout<<linyuan.a<<endl;
// cout<<linyuan.b<<endl; //报错
return 0;
}
那么继承方式讲完了,其实C++类还支持同时继承多个类例如;
#include <iostream>
using namespace std;
class father1{
public:
string name1;
father1(){
name1="小刚";
}
};
class father2{
public:
string name1;
father2(){
name1="小明";
}
};
class son:public father1,public father2{
public:
string name1;
son(){
name1="木木渊";
}
};
int main(){
son a;
cout<<a.name1<<endl;
cout<<a.father1::name1<<endl;
cout<<a.father2::name1;
}
派生类和父类继承元素重名时可以通过命名空间来分别 ,函数也是如此实现多继承;
接下来我们看一下析构函数的情况;
#include <iostream>
using namespace std;
class father1{
public:
string name1;
father1(){
cout<<"father1 构造函数"<<endl;
name1="小刚";
}
~father1(){
cout<<"father1 析构函数"<<endl;
}
};
class father2{
public:
string name1;
father2(){
name1="小明";
cout<<"father2 构造函数"<<endl;
}
~father2(){
cout<<"father2 析构函数"<<endl;
}
};
class son:public father1,public father2{
public:
string name1;
son(){
name1="木木渊";
cout<<"son 构造函数"<<endl;
}
~son(){
cout<<"son 析构函数"<<endl;
}
};
int main(){
son a;
cout<<"main 要结束了"<<endl;
}
很明显son先继承father1,在继承father2,因此构造函数先是father1,再father2,最后son,析构函数正好相反;