C++学习笔记 —— 类与对象

类中的成员默认权限是private
private: 仅在类内部可以访问
protected:子类可以访问
public:外部可以访问

#include <iostream>
using namespace std;

const double pi = 3.14;

//创建类
class Circle
{
public:
    double calculate()
    {
        return 2 * pi * m_R;
    }

    int m_R;

private:
    int m_a;
};

int main()
{
    Circle c; //创建对象

    //c.m_a = 4; 错误,priate变量和protected变量仅为类内部使用,对象不能调用。
    c.m_R = 10; //public的对象可以调用
    cout << c.calculate();
}

建议:将所有成员变量设置为private,使用public的get和set方法设置和获取私有变量的值,哪些可读可写是否添加get或者set,都可以掌控。

创建对象的几种方式

c++创建对象(四种方法)和内存分析

c++中用new和delete关键字来代替malloc和free
class 类保存在栈区,new出的对象保存在堆区。

#include <iostream>

using namespace std;

class Person
{
public:
	Person()
	{
		cout << "构造函数" << endl;
	}
	~Person()
	{
		cout << "析构函数" << endl;
	}
};
int main()
{
	//第一种:
	Person p1; //在栈区创建对象,所在函数结束会自动释放对象  不需要delete
	//第二种:
	Person(); //创建一个临时匿名对象
	Person p = Person();//效率比第一个低,这里先右边创建一个匿名对象然后调用拷贝构造给左边对象p;
	//第三种:
	Person *p2 = new Person; // new对象返回的是指针, 在堆上创建对象,new之后需要手动delete释放对象   //构造函数
	//new的对象会返回该类型的指针

	//当我们想释放堆区空间,则使用delete关键字 
	delete p2; // 析构函数
	Person *p3 = NULL; //定义对象指针, 不分配内存
}

对象占用内存

#include <iostream>

using namespace std;

class Person
{
public:
	int m_A;
	double m_B;
	void func(){};
	static int m_C;
};

void test1()
{
	cout << "size of (Person) = " << sizeof(Person) << endl;
}

int main()
{
	test1();

}
//空类 大小1
//有一个int成员变量 4;
//有2个t成员变量 16; 字节对齐,int需要和double对齐,double 8字节
//函数不占内存
//static 属性,静态成员变量不占对象内存。
//结论:只有非静态成员变量才属于对象。

构造与析构函数

构造函数的用处:初始化成员变量。

构造和析构,也就是初始化和清理
创建对象时,系统自动调用构造和析构函数,如果没有定义则系统提供默认构造和析构函数。

构造函数规则

系统会提供三个构造函数:无参构造,拷贝构造,析构函数。
系统提供三个构造函数规则:

  1. 当用户定义构造函数,系统就不提供默认无参构造。但是系统会提供默认拷贝构造函数。
  2. 当用户定义拷贝构造,则系统不提供默认无参构造和拷贝构造。
#include <iostream>
//使用iostream我们就可以使用cout和cin
using namespace std;
class Person
{
private:
	/* data */
public:
	//构造函数
	//与类名相同无返回值,可重载。
	Person();
	Person(int a);
	//拷贝构造函数 :把引用传进去,使用const不能修改该对象,拷贝构造必须加const
	Person(const Person &p);
	//析构函数,不能重载,无参数
	~Person();
};

Person::Person()
{
	cout << "无参数构造" << endl;
}
Person::Person(int a)
{
	cout << "有参数构造" << endl;
}
Person::Person(const Person &p)
{
	cout << "copy构造" << endl;
}

Person::~Person()
{
	cout << "析构" << endl;
}

int main()
{
	Person p1; // 创建对象,调用无参构造函数不加小括号 //Person p1();

	Person p2(2);			 // 创建对象,调用有参第一中方式
	Person p22 = Person(22); // 创建对象,调用有参第二种方式: Person(22)是创建匿名对象,然后把它给p22

	Person p3(p1);			 // 创建对象,调用拷贝构造函数 第一种方式
	Person p33 = Person(p1); // 创建对象,调用拷贝构造函数 第二种方式

	cout << "------main方法结束。" << endl; //方法结束之后才会调用对象的析构函数。
}
/*
无参数构造
有参数构造
有参数构造
copy构造
copy构造
------main方法结束。
析构
析构
析构
析构
析构
*/

explicit关键字

防止隐式类型转换。
在此构造函数前加explicit则第二种调用有参构造方式失效。

Person p2(2);			 // 创建对象,调用有参第一中方式
//Person p22 = Person(22); // 就不能通过该方式进行调用

深拷贝与浅拷贝

C++面试题之浅拷贝和深拷贝的区别
C++深拷贝与浅拷贝
浅拷贝:用户没有定义拷贝构造方法,系统调用默认拷贝构造。会进行简单的值拷贝,如果属性里有指向堆空间的数据,那么简单的浅拷贝会导致重复释放内存。
深拷贝:用户自己定义拷贝构造函数。​ 对于简单的类,默认的拷贝构造函数一般就够用了,我们也没有必要再显式地定义一个功能类似的拷贝构造函数。但是当类持有其它资源时,例如动态分配的内存、指向其他数据的指针等,默认的拷贝构造函数就不能拷贝这些资源了,我们必须显式地定义拷贝构造函数,以完整地拷贝对象的所有数据。

初始化的方式

初始化两种方式:

  1. 传统初始化

class Person
{
public:
	Person(int a, int b, int c)
	{
		m_a = a;
		m_b = b;
		m_c = c;
	}

	int m_a;
	int m_b;
	int m_c;
};
int main()
{
	Person p1(10, 20, 30); // 创建对象调用有参构造
	cout << "m_a :" << p1.m_a << endl; //10
	cout << "m_b :" << p1.m_b << endl; //20
	cout << "m_c :" << p1.m_c << endl; //30
}
  1. 初始化列表初始化

class Person
{
public:
	/*
	Person(int a, int b, int c)
	{
		m_a = a;
		m_b = b;
		m_c = c;
	}
	*/
	//构造函数 : 属性(参数),属性(参数){}
	Person(int a, int b, int c): m_a(a),m_b(b),m_c(c)
	{}

	int m_a;
	int m_b;
	int m_c;
};
int main()
{
	Person p1(10, 20, 30); // 创建对象调用有参构造
	cout << "m_a :" << p1.m_a << endl; //10
	cout << "m_b :" << p1.m_b << endl; //20
	cout << "m_c :" << p1.m_c << endl; //30
}

类对象作为类成员

当类对象做为类成员时候,构造顺序先将类对象一一构造,然后构造自己。当析构的时候顺序相反。

空指针访问成员函数

如果成员函数中没有调用成员变量则可以调用成员函数。
如果成员函数中包含成员变量则不可以调用。

#include <iostream>

using namespace std;

class Person
{
public:
	void show()
	{
		cout << "show" << endl;
	}
	void show2(){
		show();
	}
	void showAge()
	{
		cout << m_Age << endl;
	}

	int m_Age;
}; 

void test1()
{
	Person *p = NULL;
	p->show(); //可以访问
	p->show2();//可以访问
	//p->showAge(); //Segmentation fault: 11 不可以

}

int main()
{
	test1();
}
发布了103 篇原创文章 · 获赞 94 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/chongbin007/article/details/104350507