C++面向对象编程

  1. 引用&的使用
#include<cstdio>
#include<iostream>
using namespace std;
int main(){
	double a=3.141579;
	double &b=a;//别名
	b=99;
	cout<<"a contains:"<<a<<endl;
	system("pause");
	return 0;
}
  1. 函数重载:C++允许函数同名,只要它们的形参不一样(个数或对应参数类型),调用函数时将根据实参和形参的匹配选择最佳参数,如果有多个难以区分的最佳函数,则会报错。注意:不能根据返回类型区分同名函数!!!
#include<cstdio>
#include<iostream>
using namespace std;
double add(double a,double b){
	return a + b;
}
double add(int a,int b){
	return a + b;
}
int main(){
	double m=7,n=4;
	int i=5,j=3;
	cout<<add(m,n)<<","<<add(i,j)<<endl;
	system("pause");
	return 0;
}
  1. 运算符重载:特殊的函数重载。
#include<cstdio>
#include<iostream>
using namespace std;
struct Vector2{
	double x;
	double y;
};
Vector2 operator * (double a,Vector2 b){
	Vector2 r;
	r.x=a*b.x;
	r.y=a*b.y;
	return r;
}
Vector2 operator + (Vector2 a,Vector2 b){
	Vector2 r;
	r.x=a.x+b.x;
	r.y=a.y+b.y;
	return r;
}
ostream& operator << (ostream& o,Vector2 a){
	o<<"("<<a.x<<","<<a.y<<")";
	return o;
}
int main(){
	Vector2 k,m;
	k.x=2,k.y=-1;
	m=3.1415927*k;
	cout<<"("<<m.x<<","<<m.y<<")"<<endl;
	Vector2 n=m+k;
	cout<<"("<<n.x<<","<<n.y<<")"<<endl;
	cout<<k<<endl;//operator<<(cout,a);
	system("pause");
	return 0;
}
  1. 动态内存分配:关键字new和delete比C语言的malloc和free更好,可以对类对象调用初始化构造函数或销毁析构函数。
#include<cstdio>
#include<iostream>
using namespace std;

int main(){
	double d=3.14;//变量d是一块存放double值的内存块。
	double *dp;//指针变量dp:保存double类型的地址的变量。
	          //dp的值的类型是double *。
	         //dp是存放double *类型值的内存块。
	dp=&d;//取地址运算符&用于获得一个变量的地址。
	     //将double变量d的地址(指针)保存到double*指针变量的dp中。
	    //dp和&d的类型都是double *。
	*dp=4.14;//解引用运算符*用于获得指针变量指向的那个变量。
	        //*dp就是dp指向的那个d。
	cout<<"*dp="<<*dp<<" ,d="<<d<<endl;
	cout<<"Type a number:";
	cin>>*dp;
	cout<<"*dp="<<*dp<<" ,d="<<d<<endl;
	dp=new double;//new分配正好容纳double值的内存块
	             //并返回这个内存块的地址,而且地址的类型是double*
	            //这个地址被保存在dp中,dp指向这个新内存块,不再是原来的dp
	           //但目前这个内存块的值是未知的。
	//注意:new分配的是堆存储空间,即所有程序共同拥有的自由内存。
	//而d,dp等局部变量是这个程序自身的静态存储空间。
	//new会对这个double元素调用double类型的构造函数做初始函数。
	*dp=45.3;//*dp指向的double内存块的值变成45.3。
	cout<<"Type a number:";
	cin>>*dp;//输出dp指向的double内存块的值。
	cout<<"*dp="<<*dp<<endl;
	*dp = *dp+5;//修改dp指向的double内存块的值。
	cout<<"*dp="<<*dp<<endl;
	delete dp;//delete释放dp指向的动态分配的double内存块
	dp=new double[5];
	dp[0]=4456;//dp[0]等价于*(dp+0)。
	dp[1]=dp[0]+567;//dp[1]等价于*(dp+1)。
	cout<<"d[0]="<<dp[0]<<"  d[1]="<<dp[1]<<endl;
	delete[] dp;//释放dp指向的多个double元素占据的内存块
	           //对每个double元素调用析构函数以释放资源
	          //缺少[],只释放第一个double元素的内存块。
	system("pause");
	return 0;
}
  1. 类:是在C的struct类型上,增加了“成员函数”。
#include<cstdio>
#include<iostream>
using namespace std;
struct Date{
	int d,m,y;
	void init(int dd,int mm,int yy){
		d=dd;
		m=mm;
		y=yy;
	}
	void print(){
		cout<<y<<"-"<<m<<"-"<<d<<endl;
	}
};
int main(){
	Date day;
	day.d=10;
	day.m=20;
	day.y=30;
	day.print();//通过类Date对象day调用类Date的print方法。
	day.init(4,6,1999);//通过类Date对象day调用类Date的init方法。
	day.print();//通过类Date对象day调用类Date的print方法。
	system("pause");
	return 0;
}
  1. 自引用、成员函数重载运算符
#include<cstdio>
#include<iostream>
using namespace std;
struct Date{
	int d,m,y;
	void init(int dd,int mm,int yy){
		d=dd;
		m=mm;
		y=yy;
	}
	void print(){
		cout<<y<<"-"<<m<<"-"<<d<<endl;
	}
	Date& add(int dd){
		d = d+dd;
		return *this;//this是指向这个函数的类型对象指针。
		            //*this就是调用这个函数的那个对象。
		           //这个成员函数返回的是“自引用”,即调用这个函数本身。
		          //通过返回自引用,可以连续调用这个函数。
	}
	Date& operator+=(int dd){
		d = d+dd;
		return *this;
	}
};
int main(){
	Date day;
	day.d=10;
	day.m=20;
	day.y=30;
	day.print();//通过类Date对象day调用类Date的print方法。
	day.init(4,6,1999);//通过类Date对象day调用类Date的init方法。
	day.print();//通过类Date对象day调用类Date的print方法。
	day.add(3);
    day.add(5).add(7);
	day.print();
	day+=3;//day.add(3);
	(day+=5)+=7; //day.add(5).add(7);
	day.print();
	system("pause");
	return 0;
}
  1. 构造函数和析构函数
#include<cstdio>
#include<iostream>
using namespace std;
struct Date{
	int d,m,y;
	Date(){
		d=1;
		m=1;
		y=1000;
	std::cout<<"default constructor!"<<std::endl;
	}//如果我们没有定义构造函数,那么系统会为我们自动定义一个默认构造函数;
	//如果我们已经定义了一个构造函数那么系统就不会为我们定义默认构造函数。
	Date(int dd){
		d=1;
		m=2;
		y=1000;
	std::cout<<"default constructor!"<<std::endl;
	}
	Date(int dd,int mm){
		d=1;
		m=3;
		y=1000;
	std::cout<<"default constructor!"<<std::endl;
	}
	Date(int dd,int mm,int yy){
		d=dd;
		m=mm;
		y=yy;
		std::cout<<"constructor!"<<std::endl;
	}//构造函数没有类名并且没有返类型
	void print(){
		cout<<y<<"-"<<m<<"-"<<d<<endl;
	}
};
int main(){
	Date day;//这里必须自己在struct里面补上一个构造函数因为系统没有定义构造函数。
	Date day1(4);
	Date day2(4,6);
	Date day3(4,6,1999);//day.d day.m day.y
	day.print();
	day2.print();
	system("pause");
	return 0;
}
#include<cstdio>
#include<iostream>
using namespace std;
struct Date{
	int d,m,y;
	Date(int dd=1,int mm=1,int yy=1000){
		d=dd;
		m=mm;
		y=yy;
	std::cout<<"default constructor!"<<std::endl;
	}//如果我们没有定义构造函数,那么系统会为我们自动定义一个默认构造函数;
	//如果我们已经定义了一个构造函数那么系统就不会为我们定义默认构造函数。
	void print(){
		cout<<y<<"-"<<m<<"-"<<d<<endl;
	}
};
int main(){
	Date day;//这里必须自己在struct里面补上一个构造函数因为系统没有定义构造函数。
	Date day1(4);//dd=4,mm和yy取默认值。
	Date day2(4,6);
	Date day3(4,6,1999);//day.d day.m day.y
	day.print();
	day1.print();
	day2.print();
	day3.print();
	system("pause");
	return 0;
}
#include<cstdio>
#include<iostream>
using namespace std;

struct student{
	char *name;
	int age;
	student(char *n="no_name",int a=15){//申请内存时需要使用构造函数来打开文件或操作等,构造函数需要参数来申请空间。
		int len = strlen(n);
		name = new char[len+1];
		strcpy(name,n);
		age = a;
		std::cout<<"constructor of"<<name<<std::endl;
	}
	virtual ~student(){//析构函数是用来关闭文件和操作,释放空间的,将空间还给操作系统,因为即将销毁故不需要构造参数。
		std::cout<<"destructor!"<<name<<std::endl;
	    //delete[] name;//防止内存泄漏。
	}
};
void f(){
	student stu1;
	student stu2("wang");
	student stu3("zhang",23);
	std::cout<<stu1.name<<"\t"<<stu1.age<<std::endl;
	std::cout<<stu2.name<<"\t"<<stu2.age<<std::endl;
	std::cout<<stu3.name<<"\t"<<stu3.age<<std::endl;
}
int main(){
	f();
	system("pause");
	return 0;
}
运行结果(栈):
constructor ofno_name
constructor ofwang
constructor ofzhang
no_name 15
wang    15
zhang   23
destructor!zhang
destructor!wang
destructor!no_name
  1. 访问控制与接口
    class定义的类的成员默认都是私有的private,外部函数无法通过类对象成员或类成员函数。
    接口:public的公开成员(一般都是成员变量)称为这个类的对外接口,外部函数只能通过这些接口访问类对private等非public的包含内部细节,不对外公开,从而可以封装保护类对象!
  2. 拷贝构造函数和赋值运算符
    拷贝构造函数:定义一个类对象时用同类型的另外对象初始化。student m(s)
    赋值运算符:一个对象赋值给另外一个对象。s = k
#include<cstdio>
#include<iostream>
using namespace std;

struct student{
	char *name;
	int age;
	student(char *n="no_name",int a=0){//申请内存时需要使用构造函数来打开文件或操作等,构造函数需要参数来申请空间。
		name = new char[100];
		strcpy(name,n);
		age = a;
		cout<<"构造函数,申请了100个char元素的动态空间"<<endl;
	}
	student(const student &s){//申请内存时需要使用构造函数来打开文件或操作等,构造函数需要参数来申请空间。
		name = new char[100];
		strcpy(name,s.name);
		age = s.age;
		cout<<"拷贝构造函数"<<endl;
	}
	student& operator = (const student &s){
		name = new char[100];
		strcpy(name,s.name);
		age = s.age;
		cout<<"赋值运算符"<<endl;
		return *this;
	}
	virtual ~student(){//析构函数是用来关闭文件和操作,释放空间的,将空间还给操作系统,因为即将销毁故不需要构造参数。
	    delete[] name;//防止内存泄漏。不能用free!
		cout<<"析构函数,释放了100个char元素的动态空间"<<endl;
	}
};

int main(){
	student s;//s.name
	student k("John",56);//k.name

	student m(s);//拷贝构造函数,s与m指向同一个内存。硬拷贝 student(const student &s)
	s = k;//赋值运算符。s.operator=(k) student& operator = (const student &s)
	
	cout<<k.name<<",age"<<k.age<<endl;
	cout<<s.name<<",age"<<s.age<<endl;
	cout<<m.name<<",age"<<m.age<<endl;
	system("pause");
	return 0;
}

  1. 类体外定义成员函数
#include<cstdio>
#include<iostream>
using namespace std;
class Date{
	int d,m,y;
public:
	void print();
	Date(int dd=1,int mm=1,int yy=1000){
		d=dd;
		m=mm;
		y=yy;
	    cout<<"构造函数"<<endl;
	}
	~Date(){//析构函数名是~和类名,且不带参数,没有返回类型。
		   //目前不需要做任何释放工作,因为构造函数没申请资源。
		cout<<"析构函数"<<endl;
	}
};
void Date::print(){//Date::说明print()不是全局函数而是成员函数。
	cout<<y<<"-"<<m<<"-"<<d<<endl;
}
int main(){
	Date day;//这里必须自己在struct里面补上一个构造函数因为系统没有定义构造函数。
	day.print();
	system("pause");
	return 0;
}

11.类模板

#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
template <class T>
class Array{
	int size;
	T *data;
public:
	Array(int s){
		size=s;
		data=new T[s];
	}
	~Array(){
		delete[] data;
	}
	T &operator[](int i){
		if(i<0||i>=size){
			cerr<<endl<<"Out of bounds"<<endl;
			throw"下标超出范围";
		}else 
			return data[i];
	}
};
int main(){
	int n;
	cin>>n;
	Array<int> t(n);
	t[0]=45;
	t[4]=t[0]+6;
	cout<<"t-----"<<endl;
	cout<<t[0]<<" "<<t[4]<<endl;
	//t[10] = 7;//n如果小于10 则会报错数组超出范围
	Array<string> d(n);
	d[0]="hello";
	d[1]="world";
	cout<<"d-----"<<endl;
	cout<<d[0]<<d[1]<<endl;
	system("pause");
	return 0;
}

12.类型别名typedef

#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
typedef int INT;//如果需要修改变量类型时只需要在此处修改就行,简便了修改。

int main(){
	INT i=3;//等价于int i=3;
	cout<<i<<endl;
	system("pause");
	return 0;
}

13.string-vector

#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
typedef string String;//如果需要修改变量类型时只需要在此处修改就行,简便了修改。

int main(){
	string s1;//默认构造函数:没有参数或参数有默认值。
	String s2("hello");//普通构造函数 String就是string
	s1="yes!";//赋值运算符
	String s3(s1);//拷贝构造函数 string s3=s1;
	cout<<"s1 is:"<<s1<<endl;
	cout<<"s2 is:"<<s2<<endl;
	cout<<"s3 is:"<<s2<<endl;
	string s4("this is a C_sting",10);
	cout<<"s4 is:"<<s4<<endl;
	string s5(s4,6,4);
	cout<<"s5 is:"<<s5<<endl;
	string s6(15,'*');
	cout<<"s6 is:"<<s6<<endl;
	string s7(s4.begin(),s4.end()-5);
	cout<<"s7 is:"<<s7<<endl;
	string s8="yyye!";
	cout<<"s8 is:"<<s8<<endl;
	string s9=s1+"hello"+s2;
	cout<<"s9 is:"<<s9<<endl;
	system("pause");
	return 0;
}
#include<cstdio>
#include<iostream>
#include<string>
using namespace std;

int main(){
	string s="hell";
	string w="worl!";
	s=s+w;
	for(int ii=0;ii!=s.size();ii++)
		cout<<ii<<" "<<s[ii]<<endl;
	cout<<endl;
	string::const_iterator cii;//定义一个常量迭代器cii 不可修改只能访问!
	string::iterator ci;//定义一个普通迭代器ci 可修改
	int  ii = 0;
	for(cii=s.begin();cii!=s.end();cii++)
		cout<<ii++<<" "<<*cii<<endl;
	for(ci=s.begin();ci!=s.end();ci++){
		*ci='A';
		cout<<ii++<<" "<<*ci<<endl;
	}
	system("pause");
	return 0;
}
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
using std::cout;
using std::cin;
using std::endl;
using std::vector;
int main(){
	vector<double>student_marks;
	int num_students;
	cout<<"Number of students: "<<endl;
	cin>>num_students;
	student_marks.resize(num_students);
	for(vector<double>::size_type i=0;i<num_students;i++){
		cout<<"Enter marks for student #"<<i+1<<":"<<endl;
		cin>>student_marks[i];
	}
	cout<<endl;
	for(vector<double>::iterator it=student_marks.begin();it!=student_marks.end();it++)
		cout<<*it<<endl;
	system("pause");
	return 0;
}

14.派生类
继承(派生):一个派生类从一个或多个父类(基类)继承,即继承父类的属性和行为,但也有自己的特有属性和行为。
派生类的构造函数只能描述它自己的成员和其直接基类的初始式,不能去初始化基类的成员!如:

#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
class Employee{
	string name;
public:
	Employee(string n);
	void print();
};

class Manager:public Employee{
	int level;
public:
	Manager(string n,int l=1);
    void print();
};

Employee::Employee(string n) :name(n){//初始化成员列表
	//name = n;
}
void Employee::print(){
	cout<<name<<endl;
}
Manager::Manager(string n,int l):Employee(n),level(l){

}
void Manager::print(){
	cout<<level<<" ";
	Employee::print();
}
/*派生类的构造函数只能描述它自己的成员和其直接基类的初始式,不能去初始化基类的成员。
Manager::Manager(string n,int l):name(n),level(l){

}*/
int main(){
	Manager m("Zhang",2);
	m.print();
	Employee e("Li");
	Employee *p=&e;
	p->print();
	Manager *q=&m;
	q->print();
	system("pause");
	return 0;
}

15.虚函数和多态:
派生类的指针可以自动转化为基类指针,用一个指向基类的指针分别指向基类对象和派生类对象。

#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
class Employee{
	string name;
public:
	Employee(string n);
	void print();
};

class Manager:public Employee{
	int level;
public:
	Manager(string n,int l=1);
    void print();
};

Employee::Employee(string n) :name(n){//初始化成员列表
	//name = n;
}
void Employee::print(){
	cout<<name<<endl;
}
Manager::Manager(string n,int l):Employee(n),level(l){

}
void Manager::print(){
	cout<<level<<" ";
	Employee::print();
}
/*派生类的构造函数只能描述它自己的成员和其直接基类的初始式,不能去初始化基类的成员。
Manager::Manager(string n,int l):name(n),level(l){

}*/
int main(){
	Manager m("Zhang",2);
	Employee e("Li");
    Employee *employess[100];int num=0;
	employess[num] = &e;num++;
	employess[num] = &m;num++;//父类指针可以指向子类对象。
	system("pause");
	return 0;
}

基类指针在调用派生类函数的时候会仍然调用基类函数,虚函数就是防止该情况发生,实现了多态。

#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
class Employee{
	string name;
public:
	Employee(string n);
	virtual void print();
};

class Manager:public Employee{
	int level;
public:
	Manager(string n,int l=1);
    void print();
};

Employee::Employee(string n) :name(n){//初始化成员列表
	//name = n;
}
void Employee::print(){
	cout<<name<<endl;
}
Manager::Manager(string n,int l):Employee(n),level(l){

}
void Manager::print(){
	cout<<level<<" ";
	Employee::print();
}
/*派生类的构造函数只能描述它自己的成员和其直接基类的初始式,不能去初始化基类的成员。
Manager::Manager(string n,int l):name(n),level(l){

}*/
int main(){
	Employee *p;
	Manager m("Zhang",2);
	Employee e("Li");
	p=&e;
	p->print();
	p=&m;
	p->print();
	system("pause");
	return 0;
}
#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
class Employee{
	string name;
public:
	Employee(string n);
	virtual void print();
};

class Manager:public Employee{
	int level;
public:
	Manager(string n,int l=1);
    void print();
};

Employee::Employee(string n) :name(n){//初始化成员列表
	//name = n;
}
void Employee::print(){
	cout<<name<<endl;
}
Manager::Manager(string n,int l):Employee(n),level(l){

}
void Manager::print(){
	cout<<level<<" ";
	Employee::print();
}
/*派生类的构造函数只能描述它自己的成员和其直接基类的初始式,不能去初始化基类的成员。
Manager::Manager(string n,int l):name(n),level(l){

}*/
int main(){
	Employee *employees[100];int e_num=0;
	Employee *p;
	string name;
	int level;
    char cmd;
	while(cin>>cmd){
		if(cmd=='M'||cmd=='m'){
			cout<<"请输入姓名和级别:"<<endl;
			cin>>name>>level;
			p=new Manager(name,level);
			employees[e_num]=p;
			e_num++;
		}else if(cmd=='e'||cmd=='E'){
			cout<<"请输入姓名:"<<endl;
			cin>>name;
			p = new Employee(name);
			employees[e_num] = p;
			e_num++;
		}else
			break;
		cout<<"请输入命令:"<<endl;
	}
	for(int i=0;i<e_num;i++)
		employees[i]->print();
	system("pause");
	return 0;
}

16.多重继承、多重派生
多重继承:可以从一个类派生出多个不同的类。

class Employee{
public:
	virtual void print();
};

class Manager:public Employee{
public:
    void print();
};

class Secretary:public Employee{
public:
	void print();
}

多重派生:可以从不同的类派生出一个类来。

class One{

};

class Two{

};

class MultipleInheritance:public One,public Two{

}

17.纯虚函数和抽象类
函数体=0的虚函数称为“纯虚函数”。包含纯虚函数的类称为“抽象类”。

#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
class Animal{
protected:
	std::string m_name;
public:
	Animal(std::string name):m_name(name){ }
	std::string getName(){return m_name;}
	virtual const char* speak() = 0;
}

int main(){
	
	system("pause");
	return 0;
}

抽象类不能实例化(不能定义抽象类的对象(变量))!

#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
class Animal{
protected:
	std::string m_name;
public:
	Animal(std::string name):m_name(name){ }
	std::string getName(){return m_name;}
	virtual const char* speak() = 0;
}

int main(){
	Animal a;//错:抽象类不能实例化(不能定义抽象类的对象(变量))
	system("pause");
	return 0;
}

从抽象类派生出的类型如果没有继承实现所有功能的纯虚函数,则仍然是“抽象类”。

#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
class Animal{
protected:
	std::string m_name;
public:
	Animal(std::string name):m_name(name){ }
	std::string getName(){return m_name;}
	virtual const char* speak() = 0;
}
class Cow:public Animal{
public:
	Cow(std::string name):Animal(name){

	}
}
int main(){
	Cow cow("Betsy");//仍然错,因为Cow仍然是抽象类。
	std::cout<<cow.getName()<<"says"<<cow.speak()<<'\n';
	system("pause");
	return 0;
}

像下面这样实现所有纯虚函数就没问题了,Cow不是一个抽象类:

#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
class Animal{
protected:
	std::string m_name;
public:
	Animal(std::string name):m_name(name){ }
	std::string getName(){return m_name;}
	virtual const char* speak() = 0;
};
class Cow:public Animal{
public:
	Cow(std::string name):Animal(name){

	}
	virtual const char* speak(){
		return "Moo";
	}
};
int main(){
	Cow cow("Betsy");
	std::cout<<cow.getName()<<"says"<<cow.speak()<<'\n';
	system("pause");
	return 0;
}

18.面向对象的特征有哪些方面?

  1. 抽象:抽象就是忽略与当前目标无关的方面更充分地注意与当前目标有关的方面,又分过程抽象与数据抽象。
  2. 继承:子类的对象拥有父类的全部属性和行为,同时可以增添自己所特有的属性和行为。
  3. 封装:是指把过程和数据包围起来,对数据的访问仅仅通过已经定义了的界面。
  4. 多态性:多态性是允许不同的类的对象对同一消息做出响应,经常使用方法的重载和重写来实现方法的多态性。

19 .C++中类与结构体的区别是什么?
1.在访问机制中结构体默认访问的机制是public,而类默认访问机制是private。从class继承默认是private继承,而从struct继承默认是public继承。
2.结构体是值类型,而类是引用类型。
3.struct更适合看成是一个数据结构的实现体,class更适合看成是一个对象的实现体。
4.结构体没有析构函数,类有析构函数。

20.C和C++中结构体有什么不同?
1.在C中结构体只涉及到数据结构,在C+ +中结构体可以包含函数。
2.C++的结构体声明不必有struct关键字,而C语言的结构体声明必须带有关键字。

21.方法重载与重写的区别?
首先方法重载是允许多个同名函数同时存在并且具有不同的参数个数/类型,是类的多态性的一种表现。重载的时候要求方法名一样,参数类型和个数不一样,并且无法以返回类型别作为重载函数的区分标准。
其次方法重写是父类与子类之间的多态性,是对父类的函数进行重新定义。若子类中的新方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则子类的方法将覆盖原有的方法。

22.C++中的构造函数和析构函数区别?
①类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。
构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回void。构造函数可用于为某些成员变量设置初始值。默认的构造函数没有任何参数,但如果需要,构造函数也可以带有参数。这 样在创建对象时就会给对象赋初始值。
②类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。
析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值, 也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。
③区别:作用不同(析构函数:析构函数被调用;构造函数:为对象成员变量赋初始值)目的不同(析 构函数:”清理善后”的工作;构造函数:主要用来在创建对象时初始化对象,即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。)
23.全局变量和局部变量的区别
①作用域不同:
局部变量:“在函数内定义的变量”,即在一个函数内部定义的变量,只在本函数范围内有效。
全局变量:“在函数外定义的变量”,即从定义变量的位置到本源文件结束都有效。
②初始值不同:全局变量初始值默认为0,局部变量没有初始值。
③在同一个方法中,不允许有同名的局部变量但是在不同方法中,可以有同名的局部变量。
④在同一个类中,局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。
24.构造函数可以是虚函数吗?
不可以。
首先:构造对象的时候,必须知道对象的实际类型。而虚函数行为是在运行期间确定实际类型的,在构造对象的时,对象还没有构造成功,编译器无法知道对象的实际类型是该类本身还是其派生类。
其次:虚函数的运行依赖于虚函数指针,而在对象构造期间,虚函数指针还未构造完成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值