C++工程实战入门笔记10-面向对象之静态成员变量和成员函数、构造函数和析构函数
静态成员变量
静态成员变量在类中声明,在类外定义和初始化。它们被所有类的对象共享。
例如:static int size; 在类外定义为 int MyClass::size{0};
静态成员函数
静态成员函数不能访问非静态成员变量(因为没有this指针),只能访问静态成员变量和调用其他静态成员函数。
例如:static void TestStatic();
注:每个非静态成员函数都有一个指向当前对象的this指针
class MyClass
{
public://成员变量int x{ 0 };//C++11开始可以在声明时赋初值int y{ 0 };char name[16]{ "myclass name" };void TestIn(int v)//内联函数{//普通成员函数可以访问私有的静态成员变量count++;cout << "count = " << count << endl;//this指针:当前类对象的地址cout << "this addr = " << (long long)this << endl;x += v;y += v;cout <<"inline: "<< x << ":" << y << endl;cout << "this-: " << this->name << endl;this->Test(20);cout << name << endl;}void Test(int v);//普通函数,非内联函数,声明和定义是分开的,此处的声明,定义见下方函数 MyClass::Test(int v)// 静态成员变量声明static int size;//静态成员函数static void TestStatic(){//没有this指针 不能访问非静态成员变量count++;//可以访问静态成员变量 private: static int count;cout << "test static" << endl;//x++;不可以访问非静态成员变量 public: int x{ 0 };}//静态成员函数应用场景1:单件模式 类的对象只存在一份static MyClass& Instance(){static MyClass mc;//静态局部变量return mc;}//静态成员函数应用场景2:成员函数封装成普通函数static void RunStatic(MyClass& obj){obj.Run();}private: //私有,只有(静态)成员函数可以访问static int count;void Run() { cout << "MyClass Run" << endl; }};//以上都是放到.h头文件中
// 静态成员变量定义
int MyClass::size{ 0 };
int MyClass::count{ 0 };void MyClass::Test(int v)
{x += v;y += v;cout << "no-inline: " << x << ":" << y << endl;cout << name << endl;
}int main()
{MyClass mc;MyClass::size++;cout << "MyClass::size = " << MyClass::size << endl;//MyClass::count++;//MyClass::TestStatic();MyClass::Instance().Test(100);MyClass::RunStatic(mc);system("pause");}
全局对象和静态局部对象的构造和析构时机
构造函数
与类同名,无返回类型,用于初始化对象。在对象创建时自动调用。
析构函数
类名前加~,无参数无返回类型,用于清理资源。在对象销毁时自动调用。
- 全局对象mcg在main函数开始之前构造(在程序启动时),在main函数结束后析构(程序结束时)。
- 静态局部对象mcs在第一次执行到其声明时构造,在main函数结束后(程序结束时)析构。
- 局部对象mc1和mc2在进入它们定义的代码块时构造,在离开代码块时析构(以相反的顺序)。
- 构造函数和析构函数的定义与调用
#include<iostream>
using namespace std;class MyClass
{
public://构造函数 函数名是类名MyClass(){cout << "create myclass..." << endl;}~MyClass()//析构函数{cout << "drop myclass" << endl;}
};//MyClass:: MyClass()MyClass mcg;//全局对象 构造在main之前调用int main()
{cout << "begin main" << endl;static MyClass mcs;//静态局部 构造第一次执行{MyClass mc1;//调用MyClass构造函数MyClass mc2;getchar();//此时不调用析构函数}cout << "按任意键结束程序,此时静态对象将被销毁..." << endl;getchar(); //此时调用了析构函数--》出了作用域 调用栈区对象的析构system("pause");
}
空指针的使用
使用nullptr(C++11引入)表示空指针,比NULL更安全
释放指针后将其设置为nullptr是良好的编程习惯,可防止悬空指针
MyClass* mcp1 = new MyClass(); // 在堆上创建对象
delete mcp1; // 释放内存并调用析构函数
mcp1 = nullptr; // 指针清空用nullptr