C++基础知识第三天

cpp软件架构狮 2018-07-18 17:15:28

1.struct 的区别(C 和 C++):

C语言中只能定义变量。

C++语言中可以定义变量和函数。同时C++语言中,struct 中所有变量和函数都是 "public" 权限

2.类的封装:

3.类内部的三种权限

public:共有属性(修饰的成员变量和方法; 可以在类的内部和外部使用。)

private:私有属性(修饰的成员变量和方法,只能在类的内部使用,不能在类的外部使用)

protected:主要用于继承,保护属性(修饰的成员变量和方法; 可以在类的内部和继承的子类使用,不能在类的外部使用)

4.struct 和 class 的区别:

struct 中成员的默认权限为 public;

class 中成员的默认权限为 private;

5.类的调用(一个类调另一个类)

6.对象的构造和析构;

1)构造函数:"名称和类名相同";"没有返回值 "。"可以有多个,进行函数重载"

在内存开辟之后调用构造函数。

2)无参构造函数和有参构造函数(又分为两种)

1.无参构造函数:定义对象的时候,对象后不能加括号。如:
class stu{
stu(){"无参构造函数"}};
stu st;(正确定义对象)。

如果加上括号: stu st(); 编译的时候不会报错,(因为编译器把它当作函数声明),运行的时候会报错。

2.有参构造函数:

"普通参数": 根据形参的类型和个数,也可以进行函数重载。

class Animal{
	public:
	Animal(int age)
	{
		cout << "一个参数构造函数数字!" << endl;
		mName = "undefined";
		mAge = age;
	}
	Animal(string name)
	{
		cout << "一个参数构造函数字母!" << endl;
		mName = name;
		mAge = 0;
	}
	Animal(string name,int age)
	{
		cout << "两个参数构造函数!" << endl;
		mName = name;
		mAge = age;
	}
	//拷贝(复制)构造函数用一个对象来初始化另一个对象
	Animal(const Animal& animal)
	{ //拷贝构造函数,形参必须是引用。否则会造成死循环,一直调用它本身。本质上成了递归调用本身。
		cout << "拷贝构造函数!" << endl;
		mName = animal.mName;
		mAge = animal.mAge;
	}
}

"拷贝参数":用一个对象来初始化另一个对象

它的形参必须是引用。如果是普通变量,就会造成本质上的递归调用本身;无意义。

3)析构函数:"名称=类名+"~""; "没有返回值";"没有参数"。"一个类只可以有一个析构函数"

在内存释放之前调用析构函数。

7.构造函数调用规则: (参考上面的代码)

1) 括号法;

Animal animal1("smith"); //一个参数构造函数字母!

Animal animal2(20); //一个参数构造函数数字!

Animal animal3("John",30); //两个参数构造函数!

Animal animal4(animal3); //拷贝构造

2)显示调用构造函数(匿名对象调用拷贝构造的问题)

Animal("Smith",30); //匿名函数生命周期仅限于当前行;此行运行完后立即析构。

Animal animal5 = Animal(30); // 一个参数构造函数数字!;形参为普通变量

Animal animal5 = Animal("smith",90); 注意:/"两个参数构造函数!;拷贝构造。这行比上一行多了一个拷贝构造,是因为string容器的缘故。只有这时才会有拷贝构造"

Animal animal5(animal(30)); //一个参数构造函数数字!。

Animal animal5(animal(30,"smith")); "两个参数构造函数!;拷贝构造。" 原因同上,当不调用 string 参数时,它不会调用拷贝构造。"是由编译器处理的,具体处理方式不清楚"

"上面那两种情况,调不调用拷贝构造函数,主要看参数类型。===有string:就调拷贝构造函数;==== 没有string: 就不调拷贝构造函数===="

匿名对象如果有变量来接,它就是一个对象;"此时这个变量就相当于匿名对象的名称。"

匿名对象如果没有变量来接,他就是一个实例化对象。

Animal4("john",92); Animal(animal4); 此时当这两句在一起,编译器会报错,重定义。

3)等号法

Animal animal5 = 10; //不常用。调用一个函数构造函数

Animal animal5 = animal4l; “拷贝构造,常用

8.拷贝构造常用的两种调用方式:

Animal animal5 = animal4l;

Animal animal5(animal4l);

9.拷贝构造的调用时机:

1)对象以值传递的方式传递给函数参数。 void func(Animal animal2){ }; 用实参初始化形参,调用了拷贝构造函数

2)用一个对象初始化另一个对象。Animal animal5 = animal4l; 或者:Animal animal5(animal4l);

3)函数返回局部对象。(注意这里:debug模式和release模式不一样)。

debug模式下:会调用拷贝构造,打印两个地址也不相同。

release模式下,不会调用拷贝构造,打印的地址相同,编译器这里做了优化,直接把原来的对象返回回去了。

Animal MyBussiness()
{
	//局部对象
	Animal animal; //无参构造
	cout << &animal << endl;
	return animal; //编译器先拷贝一份,然后返回。相当于返回一个匿名对象
}
void test03()
{
	Animal animal = MyBussiness();
	cout << &animal << endl;
}

10.构造函数调用规则:

默认情况下,编译器至少为我们写的类增加三个函数

1)默认构造函数(无参,函数体为空)

默认析构函数(无参,函数体为空)

默认拷贝构造函数,对类中非静态成员属性简单 "值"拷贝。

2) 如果用户定义了"拷贝构造函数",C++不会再提供"任何默认构造函数"。

3)如果用户定义了"普通构造,"C++"不会"再提供"默认无参构造",但是"会提供默认拷贝构造"。

4)在构造函数中调用构造函数是一个危险的行为。本质上:里面的构造函数相当于一个"匿名对象"。生命周期只有本行(没有变量接的情况下)。

11.初始化列表:初始化成员列表只能在构造函数使用。

"构造函数的初始化列表顺序:"

1)当一个类中组合了其他类的对象,先执行被组合的构造函数。

2)如果组合对象有多个,来自不同的类,根据定义的顺序进行构造函数的调用,而不是初始化列表的顺序。

3)“被组合对象的构造顺序:与定义顺序有关系,与初始化列表的顺序,没有关系”

4)若类成员中有 const 修饰,必须在对象初始化的时候,给 const 元素初始化。此时就用到了"初始化列表"。

"析构函数:与构造函数的调用顺序相反。"

12.深拷贝和浅拷贝

class Person
{
	public:
	Person(int a, int b) :_b(b),_a(b){} "初始化列表"
	//"深拷贝"
	Person(const Person &p1)
	{
		mstr = (char *)malloc(strlen(p1.mstr) + 1); "核心步骤" “会进行内存拷贝”
		strcpy(mstr, p1.mstr);
		_a = p1._a;
		_b = p1._b;
	}
	//"浅拷贝"
	Person(const Person &p1)
	{
		mstr = p1.mstr; "这里只会把一个对象的指针地址,赋给另一个对象的指针。";“不会进行内存拷贝”
		_a = p1._a;
		_b = p1._b;
	}
	void print_func()
	{
		cout << _a <<" " << _b << endl;
	}
	private:
	int _a;
	int _b;
	char *mstr;
};

13.C++中 string 是一个类。

14

已知一个Print类,在该类的main()函数里执行语句 "Print a, b[2], *c;" 后;程序会自动调用该类的构造函数 4 次。

a会调用一次;b会调用两次;*c是空指针,没有开辟空间不会调用。

本页共140段,3650个字符,7342 Byte(字节)