构造函数的初始化列表
/*
日期类
*/
class CDate
{
public:CDate(int y, int m, int d)//自定义了一个构造函数,编译器就不会再产生默认构造了{_year = y;_month = m;_day = d;}void show(){cout << _year << "/" << _month << "/" << _day << endl;}
private:int _year;int _month;int _day;
};/*
构造函数的初始化列表 : 可以指定当前对象成员变量的初始化方式
CDate信息 是 CGoods商品信息的一部分 满足a part of...组合的关系
*/
class CGoods
{
public:// “CDate”: 没有合适的默认构造函数可用CGoods(const char *n, int a, double p, int y, int m, int d)//自定义了,系统不会提供默认的空构造函数了 :_date(y, m, d)//CDate _date(y, m, d); 构造对象,直接指定这个对象的初始化构造方式 ,_amount(a)//相当于是int _amount = a; 放在初始化列表:定义变量的时候直接进行了初始化 ,_price(p)//#1构造函数的初始化列表(只能写简单的初始化) 先执行 {//#2当前类类型构造函数体 后执行 strcpy(_name, n);//_amount=a;//定义在函数体,相当于是int _amount; _amount=a;存在的情况下再赋值为a//对于编译器来说,简单的初始化定义在初始化列表还是在函数体,汇编指令都是一样的,没区别 //_data=CDate(y,m,d);但是这样就是错的 ,因为CDate的默认的空构造函数系统不提供了! }void show()//打印成员变量信息 {cout << "name:" << _name << endl;cout << "amount:" << _amount << endl;cout << "price:" << _price << endl;_date.show();//访问data对象的公有方法来打印其私有信息}
private:char _name[20];int _amount;double _price;CDate _date;//成员对象 1.分配内存 2.调用构造函数
};
int main()
{CGoods good("商品", 100, 35.0, 2021, 9, 8);good.show();return 0;
}
我们看下面代码
打印的值是多少?
成员变量的初始化和它们定义的顺序有关,和构造函数初始化列表中出现的先后顺序无关!
class Test
{
public:Test(int data = 10) :mb(data), ma(mb) {}void show() { cout << "ma:" << ma << " mb:" << mb << endl; }
private://成员变量的初始化和它们定义的顺序有关,和构造函数初始化列表中出现的先后顺序无关!int ma;//ma先定义的,ma先初始化的!!! int mb;
};
int main()
{Test t;//栈的初始化是0xCCCCCCCC 即-858993460 t.show();return 0;
}
类的各种成员 - 成员方法/变量
普通的成员方法 => 编译器会添加一个this形参变量
1.属于类的作用域
2.调用该方法时,需要依赖一个对象(常对象是无法调用的 实参:const CGoods* CGoods *this)
3.可以任意访问对象的私有成员变量
static静态成员方法 => 不会生成this形参
1.属于类的作用域
2.用类名作用域来调用方法
3.可以任意访问对象的私有成员,但是仅限于不依赖对象的成员(只能调用其它的static静态成员)
const常成员方法 => const CGoods *this
1.属于类的作用域
2.调用依赖一个对象,普通对象可以调用常方法或者普通方法 ,但是常对象只能调用常方法,不能调用普通方法
3.可以任意访问对象的私有成员,但是只能读,而不能写
class CDate
{
public:CDate(int y, int m, int d)//自定义了一个构造函数,编译器就不会再产生默认构造了{_year = y;_month = m;_day = d;}void show()const{cout << _year << "/" << _month << "/" << _day << endl;}
private:int _year;int _month;int _day;
};/*
构造函数的初始化列表 : 可以指定当前对象成员变量的初始化方式
CDate信息 CGoods商品信息的一部分 a part of... 组合的关系
*/
class CGoods
{
public://“CDate”: 没有合适的默认构造函数可用CGoods(const char *n, int a, double p, int y, int m, int d):_date(y, m, d), _amount(a)//int _amount = a;, _price(p)//#1 构造函数的初始化列表{//#2 当前类类型构造函数体strcpy(_name, n);_count++;//记录所有产生的新对象的数量}//普通成员方法 常对象不能调用普通方法 void show()//打印商品的私有的信息 编译会有产生CGoods *this指针参数 ,需要接收对象的地址 {cout << "name:" << _name << endl;cout << "amount:" << _amount << endl;cout << "price:" << _price << endl;_date.show();}//常成员方法 只要是只读操作的成员方法,一律实现成const常成员方法void show()const//生成 const CGoods *this指针 {cout << "name:" << _name << endl;cout << "amount:" << _amount << endl;cout << "price:" << this->_price << endl;_date.show();//const CGoods *this}//静态成员方法 没有this指针 不需要接收对象的地址,不用对象来调用 是所有对象共享的信息 static void showCGoodsCount()//打印的是所有商品共享的信息{cout << "所有商品的种类数量是:" << _count << endl;//不能打印_name这些成员变量,因为不知道是谁的_name,静态方法里没对象,不能访问对象的成员变量,只能访问静态成员变量 }
private:char _name[20];int _amount;double _price;CDate _date;//成员对象 1.分配内存 2.调用构造函数static int _count;//静态成员变量不属于对象,而是属于类级别的声明,用来记录商品对象的总数量
};
//static成员变量一定要在类外进行定义并且初始化,静态的成员变量在.bss段中,对象在栈上
int CGoods::_count = 0;
int main()
{CGoods good1("商品1", 100, 35.0, 2019, 5, 12);good1.show();CGoods good2("商品2", 100, 35.0, 2019, 5, 12);good2.show();CGoods good3("商品3", 100, 35.0, 2019, 5, 12);good3.show();CGoods good4("商品4", 100, 35.0, 2019, 5, 12);good4.show();//统计所有商品的总数量CGoods::showCGoodsCount();//4const CGoods good5("非卖品商品5", 100, 35.0, 2019, 5, 12);//不能修改,只能看,不能改动 good5.show();//CGoods::show(&good5) const CGoods* -> const CGoods *thisreturn 0;
}
指向类成员变量的指针
运行报错
正确写法:
静态变量呢?
#include <iostream>
using namespace std;class Test
{
public:void func() { cout << "call Test::func" << endl; }//普通的成员方法 static void static_func() { cout << "Test::static_func" << endl; }//静态的成员方法 int ma;//普通的成员变量 static int mb;//静态成员变量
};
int Test::mb;
int main()
{Test t1;Test *t2 = new Test();//int a=10; int *p=&a; *p=30;//无法从“int Test::* ”转换为“int *”int Test::*p = &Test::ma;t1.*p = 20;//必须加上对象的调用,才能访问普通的成员变量或者成员方法cout << t1.*p << endl;t2->*p = 30;cout << t2->*p << endl;int *p1 = &Test::mb;//不依赖对象,普通指针指向就可以了*p1 = 40;cout << *p1 << endl;delete t2;//堆上的对象要delete手动释放 return 0;
}
指向类成员方法的指针
这样是错误的。
正确做法:
#include <iostream>
using namespace std;class Test
{
public:void func() { cout << "call Test::func" << endl; }//普通的成员方法 static void static_func() { cout << "Test::static_func" << endl; }//静态的成员方法 int ma;//普通的成员变量 static int mb;//静态成员变量
};
int Test::mb;
int main()
{Test t1;Test *t2 = new Test();//指向成员方法的指针//无法从“void (__thiscall Test::* )(void)”转换为“void (__cdecl *)(void)”void (Test::*pfunc)() = &Test::func;(t1.*pfunc)();(t2->*pfunc)();//如何定义函数指针指向类的static成员方法呢?//定义一个普通的指针就可以了 delete t2;//堆上的对象要delete手动释放 return 0;
}