cplus class - yaokun123/php-wiki GitHub Wiki
一、类和对象
1.1、类
- c++中可以使用struct、class来定义一个类
struct和class的区别:
struct的默认权限是public
class的默认权限是private
// 类的定义
struct Person{
// 成员变量
int m_age;
// 成员函数
void run(){
cout << m_age << " run() " << endl;
}
};
// 类的定义
class Person{
public:
// 成员变量
int m_age;
// 成员函数
void run(){
cout << m_age << " run() " << endl;
}
};
Person person;
// 访问Person对象的成员变量
person.m_age = 10;
// 用Person对象调用成员函数
person.run();
// 通过指针间接访问person对象
Person *p = &person;
p->m_age = 30;
p->run();
// 上面代码中person对象、p指针的内存都是在函数的栈空间,自动分配和回收的。
// 变量名命名参考
全局变量:g_
成员变量:m_
静态变量:s_
常量:c_
1.2、this
对象中只保存普通成员变量,成员方法保存在代码区(只有一份)对象调用成员方法时会自动将对象地址(this)传递给函数。
二、封装
- 成员变量私有化,提供公共的getter和setter给外界去访问成员变量。
class Person{
private:
int m_age;
public:
void setAge(int age){
m_age = age;
//this->m_age = age;
}
int getAge(){
return m_age;
//return this->m_age;
}
};
// 调用
Person person;
person.setAge(20);
cout << person.getAge() << endl;
三、内存空间的布局
- 每个应用都有自己独立的内存空间,其内存空间一般都哟哟以下几大区域。
- 代码段
- 数据段
- 栈空间
- 堆空间
- 堆空间 申请和释放
1、malloc/free
2、new/delete
int *p = new int;
*p = 10;
delete p;
3、new[]/delete[]
四、构造方法
构造函数,在对象创建的时候自动调用,一般用于完成对象的初始化工作。
函数名与类名相同,无返回值(void都不能写),可以有参数,可以重载,可以有多个构造函数。
一旦自定义了构造函数,必须用其中一个自定义的构造函数来初始化对象。
通过malloc分配的对象不会调用构造函数
在某些特定的情况下(待定),编译器才会为类生成空的无参的构造函数。
struct Person{
int m_age; // 不会生成默认的无参构造函数
};
struct Person{
int m_age = 0; // 生成默认的无参构造函数
};
五、默认情况下成员变量的初始化
全局区:初始化为0
栈区:没有初始化成员变量
堆区:加小括号的会初始化为0,不加
六、析构函数
析构函数在对象销毁的时候自动调用,一般用于完成对象的清理工作。
函数名以~开头,与类名同名,无返回值(void都不能写),无参,不可以重载,有且只有一个。
通过malloc分配的对象free时候不会调用析构函数
析构函数要声明为public才能够被外界正常使用
八、声明和实现分离
class Person{
private:
int m_age;
public:
void setAge(int age){
m_age = age;
}
int getAge(){
return m_age;
}
Person(){
m_age = 0;
}
~Person(){
}
};
-----------------------------------------------------------------
// 声明
class Person{
private:
int m_age;
public:
void setAge(int age);
int getAge();
Person();
~Person();
};
// 实现
void Person::setAge(int age) {
m_age = age;
}
int Person::getAge() {
return m_age;
}
Person::Person() {
m_age = 0;
}
Person::~Person() {
}
九、命名空间
默认的全局命名空间,没有名字,直接使用::访问
如果重复定义命名空间,会自动合并
// 命名空间的声明
namespace ns1{
class Person{
public:
int m_age;
};
}
namespace ns2{
class Person{
public:
int m_weight;
};
}
// 命名空间的使用
ns1::Person person1;
ns2::Person person2;
using namespace ns1; // 说明之后的代码使用ns1的命名空间内容
Person person3;
十、继承
继承可以让子类拥有父类的所有成员(变量/函数)
子类的构造函数默认会调用父类的无参构造函数
如果子类的构造函数显式地调用了父类的有参构造函数,就不会再去默认调用父类的无参构造函数。
如果父类缺少无参构造函数,子类的构造函数必须显示调用父类的有参构造函数。
class Person{
public:
int m_age;
void run(){
cout << "Person" << endl;
}
};
class Student : Person{ // 继承
public:
int m_class;
};
十一、成员访问权限
public:公共的在任何地方都可以访问
protected:子类内部、当前类内部可以访问
private:私有的,只有当前类内部可以访问
子类内部访问父类成员的权限,是以下2项中权限最小的那个
1、成员本身的访问权限
2、上一级父类的继承方式
十二、初始化列表
是一种便捷的初始化成员变量的方式
class Person{
public:
int m_age;
int m_height;
/*Person(int age, int height){
m_age = age;
m_height = height;
};*/
Person(int age, int height) : m_age(age),m_height(height){ // 初始化列表
}
};
构造函数的相会调用
class Person{
public:
int m_age;
int m_height;
// 构造函数调用构造函数不能这样调用
/*Person(){
Person(0,0); // 实际上是在创建一个新的Person对象
}*/
// 只能放到初始化列表中
Person() : Person(0,0){
}
Person(int age, int height){
m_age = age;
m_height = height;
};
};