《C++语言程序设计基础》学习之函数

类构造函数:
类中没有指定变量属性的,如public、private、protect,默认是private属性,不可以在类外访问private属性的变量
使用函数将实参传给形参时,从最后的参数开始传,依次传前面的参数
类建立的时候有默认的构造函数和析构函数,可以重新建立构造函数

class Clock {
public:
	Clock(int newH, int newM, int newS);//构造函数
	//Clock();//默认构造函数
	void setTime(int newH = 0, int newM = 0, int newS = 0);
	void showTime();
private:
	int hour, minute, second;
};
void Clock::setTime(int newH, int newM, int newS) {
	hour = newH;
	minute = newM;
	second = newS;
}

如果不带参数这样声明,Clock c;
就会报错所以还需要声明个默认的构造函数

class Clock {
public:
	Clock(int newH, int newM, int newS);//构造函数
	Clock();//默认构造函数
	void setTime(int newH = 0, int newM = 0, int newS = 0);
	void showTime();
private:
	int hour, minute, second;
};

Clock::Clock(int newH, int newM, int newS):
	hour(newH), minute(newM), second(newS) {
	}
Clock::Clock():hour(0),minute(0),second(0){}  //Clock(0,0,0)

这样声明Clock c1(10, 10, 0);  Clock c2;就不会报错,前者调用Clock(int newH, int newM, int newS)函数,后者调用默认构造函数。
C++11标准中增加的委托构造函数,构造函数可以调用其他已经编写好的构造函数,这个可以改写Clock::Clock():hour(0),minute(0),second(0){} ;为Clock::Clock():Clock(0,0,0) {} ;
复制构造函数:类中有默认的复制构造函数,用类已经存在的对象初始化新对象,使用引用作为构造函数的参数,为了引用以后不改变之前对象的值,需要用const关键字限定

class 类名 {
public
    类名形参);//构造函数
    类名const  类名 &对象名);//复制构造函数

    //       ...
};
类名::类( const  类名 &对象名)//复制构造函数的实现
{    函数体    }

复制构造函数被调用的几种情况:

l  定义一个对象时,以本类另一个对象作为初始值,发生复制构造;
l  如果函数的形参是类的对象,调用函数时,将使用实参对象初始化形参对象,发生复制构造;
l  如果函数的返回值是类的对象,函数执行完成返回主调函数时,将使用return语句中的对象初始化一个临时无名对象,传递给主调函数,此时发生复制构造。

C++11标准中使用    类名 (const 类名& 对象) =delete;  //指示编译器不生成默认复制构造函数
复制构造函数的形参如果不使用const限定,引用修改会导致被引用对象的修改

class Point {
public:
	Point(int xx = 0, int yy = 0) { x = xx; y = yy; }//构造函数
	Point(const Point&p);//复制构造函数
	int getX() { return x; }
	int getY() { return y; }
private:
	int x, y;//私有数据
};
//成员函数的实现
Point::Point(const Point &p) {
	x = p.x;
	y = p.y;
	cout << "Calling the copy constructor" << endl;
}
//返回值为Point 类对象的函数
Point fun2() {
	Point a;
	return a;
}
//主程序
void fun1(Point p) {
	cout << p.getX() << endl;
	//p.setX(1);
}
int main(){
	Point a; //第一个对象A
	Point k(a); //情况一,用A初始化K。第一次调用复制构造函数
	cout << k.getX() << endl;
	fun1(k);    //情况二,对象k作为fun1的实参,形参赋值给实参,第二次调用复制构造函数
	k = fun2();   //情况三,函数的返回值是类对象,函数返回时,调用复制构造函数
	cout << k.getX() << endl;
	return 0;
}

析构函数不能有参数也不能有返回值即return语句

类的组合:用已经存在的类组装新的类,类中的成员是其他类的对象,可以将类看成是特殊的数据类型,如int,可以在已有抽象的基础上实现更复杂的抽象

原则:不仅要负责对本类中的基本类型成员数据初始化,也要对对象成员初始化。
类名
::类名(对象成员所需的形参,本类成员形参)
:对象1(参数),对象2(参数)......{
//函数体其他语句
}

构造组合类对象时的初始化次序

首先对构造函数初始化列表中列出的成员(包括基本类型成员和对象成员)进行初始化,初始化次序是成员在类体中定义的次序。
处理完初始化列表之后,再执行构造函数的函数体。
 成员对象构造函数调用顺序:按对象成员的声明顺序,先声明者先构造。
 初始化列表中未出现的成员对象,调用用默认构造函数(即无形参的)初始化

 处理完初始化列表之后,再执行构造函数的函数体。

class Point {	//Point类定义
public:
	Point(int xx = 0, int yy = 0) {
		x = xx;
		y = yy;
	}
	Point(Point &p);
	int getX() { return x; }
	int getY() { return y; }
private:
	int x, y;
};
Point::Point(Point &p) {	//复制构造函数的实现
	x = p.x;
	y = p.y;
	cout << "Calling the copy constructor of Point" << endl;
}
//类的组合
class Line {
public:
	Line(Point xp1, Point xp2);
	Line(Line &l);
	double getLen() { return len; }
private:
	Point p1, p2;
	double len;
};
//组合类的构造函数
Line::Line(Point xp1, Point xp2) : p1(xp1), p2(xp2) {
	cout << "Calling constructor of Line" << endl;
	double x = static_cast<double>(p1.getX() - p2.getX());
	double y = static_cast<double>(p1.getY() - p2.getY());
	len = sqrt(x * x + y * y);
}
Line::Line(Line &l) : p1(l.p1), p2(l.p2) {//组合类的复制构造函数
	cout << "Calling the copy constructor of Line" << endl;
	len = l.len;
}
//主函数
int main() {
	Point myp1(1, 1), myp2(4, 5);	//建立Point类的对象

//调用组合构造函数,调用four次Point复制构造函数,其中复制实参给形参调用,组合类构造函数赋值调用 建立Line类的对象
	Line line(myp1, myp2);	

//调用Line的复制构造函数,赋值时调用Point复制构造函数,按照Line类中声明时的次序赋值p1、p2
	Line line2(line);	//利用复制构造函数建立一个新对象

	cout << "The length of the line is: ";
	cout << line.getLen() << endl;
	cout << "The length of the line2 is: ";
	cout << line2.getLen() << endl;
	return 0;
}

 c++中的结构体是特殊的类,默认的数据成员是public属性的,可以定义函数
如果一个结构体的全部数据成员都是公共成员,并且没有用户定义的构造函数,没有基类和虚函数(基类和虚函数将在后面的章节中介绍),这个结构体的变量可以用下面的语法形式赋初值
类型名 变量名 = { 成员数据1初值, 成员数据2初值, …… };

枚举类语法形式:enum class 枚举类型名: 底层类型 {枚举值列表}; 底层类型默认是整形
如enum class Category { General=1, Pistol, MachineGun, Cannon}; 则Pistol=2,MachineGun=3,Cannon=4
转换限制,枚举类对象不可以与整型隐式地互相转换。
使用Type的枚举值General:Category::General

enum class Side{ Right, Left };
enum class Thing{ Wrong, Right };  //不冲突
int main()
{
Side s = Side::Right;
Thing w = Thing::Wrong;
cout << (s == w) << endl;  //编译错误,无法直接比较不同枚举类
return 0;
}

引用的开销比较小,因为只是传递指针,相当于变量多个名字

int i,j;
int &ri=i; //ri引用 赋值为i的
j=10;
ri=j; //ri赋值为j, 由于ri是引用,所以i也赋值为j

相当于i=j,引用是可以作为形参的
函数一般情况是单向传递的,形参在函数被调用的时候会分配存储空间,相当于将实参的值复制给形参,被调用以后,形参有自己的内存空间,所以形参在函数中的变化是不会传递给实参的,函数是单向传递的。要实现参数的双向传递,可以传递引用。
类对象作为函数参数的时候,有时候时间和空间的开销会比较大,这个时候传值就不太合适,由于引用的开销比较小,传引用就好,但是传引用又不希望双向传递。

猜你喜欢

转载自blog.csdn.net/shiheyingzhe/article/details/82903555