c++随记一(黑马程序员学习笔记)

1、当结构体作为参数直接输入函数中时,如果结构体过于大,则全部再复制一次开销也十分大,一般使用地址传参。如果怕被不小心更改,则在参数前加入const修饰。

2、常量指针 const int * p =&a
指针指向可以更改,但值不可更改。
指针常量 int * const p =&a
指针指向不可更改,但值可以更改。

3、无论什么类型的指针,32位系统下占4个字节,64位系统下占8个字节。

4、内存分为代码区、全局区、栈区和堆区。其中,代码区作用是存放二进制的代码由操作系统进行管理;全局区存放全局变量和静态变量,同时还包含了常量区,包括字符串常量和const修饰的全局常量,在程序结束后由操作系统释放;栈区存放局部变量,参数,由编译器自动释放,注意,不要返回局部变量的地址;堆区由程序员申请释放,程序结束时也会释放,一般用new来申请。

5、引用即起一个别名。如int &b = a。引用必须初始化,且引用在初始化后,不可以改变。引用传递函数参数时,形参也会修饰实参。引用函数返回值时,不要返回局部变量的引用,函数调用可以作为左值。C++内部引用本质就是指针常量.

6、如果函数有一个变量有了默认参数,那么这个默认参数往后都必须有默认参数。函数声明与函数实现里面只能有一个有默认参数。函数占位参数,如int aaaa(int),占位参数也可以有默认参数,如int aaaa(int = 10)。

7、函数重载(函数名相同)。满足条件:作用域相同,但函数参数不同或参数类型不同或顺序不同。返回值不能作为重载的条件(如void XXX和int XXX)。引用可以重载,const添加与不添加是两个不同的参数类型

8、C++封装继承多态。struct默认权限是Public,而class默认权限是私有。m设置成员属性私有可以自己控制读写,也可以检查数据的有效性。

9、构造函数和析构函数。用于初始化和清理。构造函数有参数,可以发生重载,而析构函数没有参数,不能重载。构造和析构如果自己不提供,编译器会自动空实现一个。构造函数可以分为无参构造和有参构造,或者分为普通构造和拷贝构造Person(const Person &p)。调用默认构造函数的时候,后面不要跟括号,直接Person p,否则编译器会把它当作函数声明。匿名对象,如Person(10),当前行结束后系统会回收。不要用拷贝构造函数初始化匿名对象,编译器会认为是重定义。
调用构造函数三种方法:

//1、括号法
Person p1;//默认构造函数
Person p2(10);//有参构造函数
Person p3(p2);//拷贝构造函数
//2、显示法
Person p1;
Person p2 = Person(10);
Person p3 = Person(p2);
//3、隐式转换法
Person p4 = 10//与上面P2相同,有参构造
Person p5 = p4;

10、拷贝构造函数调用时机
(1)使用一个已经构造完毕的对象来初始化一个新的对象。(2)值传递的方式给函数参数传值。(3)以值方式返回局部对象(return p)。

11、构造函数调用规则。创建一个类编译器默认添加默认构造、析构函数、拷贝构造(值拷贝)。

12、浅拷贝:简单拷贝;深拷贝:堆区重新申请空间再进行拷贝。为了防止堆区内存重复释放,因此出现深拷贝。

13、静态成员函数只能访问静态成员变量,因为非静态成员变量无法区分究竟是哪个对象的。静态成员函数:所有程序共享同一个函数。静态成员函数也是有访问权限的。

14、成员变量和成员函数是分开存储的。空对象所占的内存空间为1。因为C++编译器给空对象一个字节的空间,为了区分空对象占内存的位置。非静态成员变量,属于类的对象上,静态成员变量不属于类的对象上。非静态成员函数和静态成员函数也不属于类的对象上。

15、this指针。(1)解决名称冲突。

class Person//这里就会导致编译器无法区分age
{
public:
    Person(int age)
    {age = age;}
    int age
}
class Person//this指针指向的是被调用的成员函数所属对象
{
public:
    Person(int age)
    {this->age = age;}
    int age
}

(2)返回对象本身用*this

class Person
{
public:
    Person & PersonAddPerson(Person p)
    {
       this->age += p.age;
       return *this;
    }
}

16、空指针可以调用成员函数,但不能调用有this的函数,如果有this可以前面加个if判断指针若为空则直接返回。

17、this指针是指针常量,指向不可修改。const修饰成员函数格式是 void 函数名() const。在成员函数名后面加const,本质是让this指针指向的值也不能修改。但可以在变量前加关键字mutable后在常函数中仍然可以修改。

18、常对象是在对象前加const。但mutable也可修改。常对象只能调用常函数。

19、友元的目的是让一个函数或者类访问另一个类中的私有成员。三种实现方法:全局函数做友元,类做友元,成员函数做友元。全局函数做友元只需要在类中添加声明,声明前添加friend。类做友元,只需要在类中添加friend class XXX;成员函数做友元friend void 类名::函数名();

20、类外实现成员函数

Building::Building()
{
   m_sittingRoom = "客厅";
}

21、对于内置的数据类型的表达式的运算符是不可能改变的。

#include<iostream>
using namespace std;
//加号运算符重载
class Person
{
public:
	//1、成员函数重载
	/*Person operator+(Person& p)
	{
		Person temp;
		temp.m_A = this->m_A + p.m_A;
		temp.m_B = this->m_B + p.m_B;
		return temp;
	}*/
public:
	int m_A;
	int m_B;
};
//2、全局函数重载
Person operator+(Person& p1, Person& p2)
{
	Person temp;
	temp.m_A = p1.m_A + p2.m_A;
	temp.m_B = p1.m_B + p2.m_B;
	return temp;
}
Person operator+(Person& p1, int val)
{
	Person temp;
	temp.m_A = p1.m_A + val;
	temp.m_B = p1.m_B + val;
	return temp;
}
void test01()
{
	Person p1;
	p1.m_A = 10;
	p1.m_B = 10;
	Person p2;
	p2.m_A = 10;
	p2.m_B = 10;
	//全局函数本质调用
	//Person p3 = operator+(p1, p2);
	//成员函数本质调用
	//Person p3 = p1.operator+(p2);
	Person p3 = p1 + p2;
	//运算符重载也可以发生函数重载
	Person p4 = p3 + 10;
	cout << "p4.m_A = " << p4.m_A << endl;
	cout << "p4.m_B = " << p4.m_B << endl;
}

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

22、左移运算符重载使其可以输出自定义的数据类型。但通常不会利用成员函数来实现左移的重载,因为无法实现cout在左侧。

//只能利用全局函数重载左移运算符
ostream &operator<<(ostream &cout, Person &p)
{
	cout << "m_A = " << p.m_A << " m_B = " << p.m_B;
	return cout;
}

函数名称前面加引用符号“&”,代表该函数返回值类型是引用。如:int &operate+(…);

23、赋值运算符重载,是因为如果类中有堆区指针,在进行系统赋值时是浅拷贝,如果调用析构函数会造成重复释放。因此重载赋值运算符。首先先将原本存在的堆区释放干净,再重新分配一块内存。如果想要连续赋值,需要return *this,函数类型用Person&,引用保证不是值传递。

#include<iostream>
using namespace std;

class Person
{
public:
	Person(int age)
	{
		m_Age = new int(age);
	}
	~Person()
	{
		if (m_Age != NULL)
		{
			delete m_Age;
			m_Age = NULL;
		}
	}
	//重载 赋值运算符
	Person& operator=(Person& p)
	{
		//先判断是否有属性在堆区,如果有先释放干净再深拷贝
		if (m_Age != NULL)
		{
			delete m_Age;
			m_Age = NULL;
		}
		m_Age = new int(*p.m_Age);
		//返回对象本身
		return *this;
	}
	int* m_Age;
};
void test01()
{
	Person p1(18);
	Person p2(20);
	Person p3(30);

	p3 = p2 = p1;
	cout << "p1的年龄为:" << *p1.m_Age << endl;
	cout << "p2的年龄为:" << *p2.m_Age << endl;
	cout << "p3的年龄为:" << *p3.m_Age << endl;
}
int main()
{
	test01();
	return 0;
}

24、函数调用运算符重载(仿函数),即重载()。其中还有匿名函数对象。

#include<iostream>
#include<string.h>
using namespace std;

class MyPrint
{
public:
	void operator()(string test)
	{
		cout << test << endl;
	}
};
void test01()
{
	MyPrint myPrint;
	//使用起来非常像函数调用,因此成为仿函数
	myPrint("hello world");
}
//仿函数非常灵活,没有固定写法
class MyAdd
{
public:
	int operator()(int num1, int num2)
	{
		return num1 + num2;
	}
};
void test02()
{
	MyAdd myAdd;
	int ret = myAdd(100, 100);
	cout << "ret = " << ret << endl;
	//匿名函数对象
	cout << MyAdd()(100, 100) << endl;
}
int main()
{
	test01();
	test02();
	system("pause");
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章