类与对象
定义一个类class Box{public: //指定成员的访问权限,包括数据成员和方法成员double length; // 类的数据成员,``类中的数据和方法称为类的成员}; //需要有分号
定义对象Box box1;
访问数据成员 box1.length=5.0;只有public成员可以通过.进行访问,私有和受保护成员不可以
访问成员函数也是对象用**.**操作符,不能像普通函数一样直接调用
c++中,在类内部不能对数据成员直接赋值,比如class Box{ public:double length=0.0;};这是错的**
成员函数
成员函数可以定义在类定义内部,或者单独使用范围解析运算符 :: 来定义
在类定义中定义的成员函数也为内联函数。class Box{public:double getVolume(void){ return length * breadth * height; } };
此为成员函数
也可以定义在类外,使用范围解析运算符 :: 来定义 ,在函数名前加上 类名::即可
定义在类外时类内要声明函数
class Box{public:double getVolume(void);// 声明函数};double Box::getVolume(void){return length * breadth * height;}
c++中如果定义函数无参,最好写上带void,不要直接写(),应该(void),一种规范
**
内联函数
使用inline定义,比如inline int Max(int x, int y) { return (x > y)? x : y; }
内联函数一般与类一起使用(约等于成员函数,但是定义在类外)
在类定义中定义的成员函数也为内联函数
数据隐藏
数据隐藏是防止直接访问类类型的内部成员。
通过在类主体内部对各个区域标记 public(公有)private(私有)protected** (受保护)这三个访问说明符实现
内联函数就是让编译器自动将内联函数内容(函数体)扩展到调用处。减少调用时间,以空间换时间;
当一个函数不太复杂,但是频繁调用。可以声明为内联函数**
成员和类的默认访问修饰符是 private。
一个类可以有多个 public、protected 或 private 标记区域。class Base {public:// public members go hereprotected:// protected members go hereprivate:// private members go here};
- 公有成员在程序中类的外部是可访问的。您可以不使用任何成员函数来设置和获取公有变量的值
- 私有成员变量或函数在类的外部是不可访问的,甚至是不可查看的。只有类和友元函数可以访问私有成员。
- 保护成员变量或函数与私有成员十分相似,但有一点不同,保护成员在派生类(即子类)中是可访问的
实际操作中,我们一般会在私有区域定义数据,在公有区域定义相关的函数,以便在类的外部也可以调用这些函数
构造函数
类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。
构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。
构造函数定义方法和成员函数一样,**只不过声明时不用写返回值,参数为void时声明不写void
构造函数带参数列表自然可以重载class Line{public:`** Line(); ** // 这是构造函数<br />};<br />Line::Line(void)<br />{<br /> cout << “Object is being created” << endl;<br />}<br />c++的构造函数不像java一样要通过new ?()调用,是**类创建新对象时自动调用**<br />**<br />**带参的构造方法**<br />类中声明:Line(double len);<br />定义Line::Line( double len) { cout << “Object is being created, length = “ << len << endl; length = len; }<br />主函数创建对象自动调用构造函数Line line(10.0);` 成员变量length就被赋予了10.0
使用初始化列表来初始化字段:Line::Line( double len): length(len){ //这种形式:length(len)执行顺序是比cout...先执行cout << "Object is being created, length = " << len << endl;}
相当于上面的Line::Line( double len) {cout << "Object is being created, length = " << len << endl;length = len; }
假设有一个类 C,具有多个数据成员X、Y、Z 等需要进行初始化,同理地,您可以使用上面的语法,只需要在不同的字段使用逗号进行分隔,如下所示:C::C( double a, double b, double c): X(a), Y(b), Z(c){....}

析构函数
类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。(一般对象在离开其作用域时被删除,这里简单理解成程序执行完对象所在区域时被删除)
- 析构函数的名称与类的名称是相似的,只是在前面加了个波浪号(~)作为前缀;
以上只是告诉你析构函数名称跟构造函数相似,但是不一样
- 它不会返回任何值,也不能带有任何参数。(所以析构函数不能重载)(虽然可以看成是返回void,但是实际上连void都不应该有,不然内存还是释放不干净)
析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。
析构函数用法上跟构造函数一样,就是名称前多了个~Line(); // 这是构造函数声明 ~Line(); // 这是析构函数声明Line::Line(void){cout << "Object is being created" << endl;}Line::~Line(){cout << "Object is being deleted" << endl;}
拷贝构造函数
拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:
- 通过使用另一个同类型的对象来初始化新创建的对象。
- 复制对象把它作为参数传递给函数。
- 复制对象,并从函数返回这个对象。
如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。拷贝构造函数的最常见形式如下:
classname (const classname &obj) {
// 构造函数的主体
}
具体https://www.w3cschool.cn/cpp/cpp-copy-constructor.html
友元函数
友元函数是定义在类外部,**但有权访问类的所有私有(private)成员和保护(protected)成员。(自然也可以访问public成员)尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。
这意味着友元函数可以像普通函数一样直接调用,但是却可以访问类的全部成员,但是又不需要借助对象就直接调用
友元函数以牺牲数据的封装性和隐蔽性,提高了程序的运行效率
友元
友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,该类整个类及其所有成员都是友元。
语法
另外一个类B声明函数为Box的友元,需要在类定义中该函数原型前使用关键字 friendclass Box{double width;public:double length;friendvoid B::printWidth( Box box ); 友元函数虽然定义在类外,但是类内要进行声明,但是类外定义是如同普通函数一样定义,而不是通过范围解析符::void setWidth( double wid );};
声明类 ClassTwo 的所有成员函数作为类 ClassOne 的友元,在类 ClassOne 的定义时前加上friend关键字即可friend class ClassTwo;//跟classone没关系
this指针
在 C++ 中,每一个对象都能通过 this 指针来访问自己的地址。this** 指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象。
友元函数没有 this 指针,因为友元不是类的成员。只有成员函数才有 this** 指针。
用法为this->? ?为成员,this->?就相当于 调用this所在成员函数的对象.成员
this指针好处在于同样的代码可以使用不同对象的不同成员
#include <iostream>using namespace std;class Box{public:// 构造函数定义,带有默认参数Box(double l=2.0, double b=2.0, double h=2.0){cout <<"Constructor called." << endl;length = l;breadth = b;height = h;}double Volume() //返回体积{return length * breadth * height;}int compare(Box box) //定义比较体积的函数{//this调用传入compare的对象参数本身,并且让该对象调用成员函数Volume()return this->Volume() > box.Volume();}private:double length; // Length of a boxdouble breadth; // Breadth of a boxdouble height; // Height of a box};int main(void){Box Box1(3.3, 1.2, 1.5); // Declare box1Box Box2(8.5, 6.0, 2.0); // Declare box2if(Box1.compare(Box2)){cout << "Box2 is smaller than Box1" <<endl;}else{cout << "Box2 is equal to or larger than Box1" <<endl;}return 0;}当上面的代码被编译和执行时,它会产生下列结果:Constructor called.Constructor called.Box2 is equal to or larger than Box1
int compare(Box box) //定义比较体积的函数{//this调用传入compare的对象参数本身,并且让该对象调用成员函数Volume()return this->Volume() > box.Volume();}
if(Box1.compare(Box2))
最重要的就这两部代码第一步是比较函数,第二部是调用比较函数return this->Volume() > box.Volume();
转为return 调用比较函数的对象->Volume() > 参数对象.Volume();
再转为return Box1->Volume() > Box2.Volume();
最后为return Box1.Volume() > Box2.Volume();
静态成员
static 关键字来把类成员定义为静态的。当我们声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本。
静态成员在类的所有对象中是共享的。如果不存在其他的初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零。我们不能在类的定义中初始化静态成员,但是可以在类的外部通过使用范围解析运算符 :: 来重新声明静态变量从而对它进行初始化
类内要声明下静态成员static 数据类型 静态成员名; static和类型修饰符无先后之分,都是前缀静态数据成员的数据类型 类::静态成员名=?;
以上指的是静态数据成员
无论是静态数据成员还是静态函数成员,都可以不借助对象直接通过类调用(但是也可以借助对象进行调用)
#include <iostream>using namespace std;class Box{public:static int objectCount;// 构造函数定义Box(double l=2.0, double b=2.0, double h=2.0){cout <<"Constructor called." << endl;length = l;breadth = b;height = h;// 每次创建对象时增加 1objectCount++;}double Volume(){return length * breadth * height;}private:double length; // 长度double breadth; // 宽度double height; // 高度};// 初始化类 Box 的静态成员int Box::objectCount = 0;int main(void){Box Box1(3.3, 1.2, 1.5); // 声明 box1Box Box2(8.5, 6.0, 2.0); // 声明 box2// 输出对象的总数cout << "Total objects: " << Box::objectCount << endl;return 0;}当上面的代码被编译和执行时,它会产生下列结果:Constructor called.Constructor called.Total objects: 2
静态函数成员
静态函数成员比静态数据成员要简单的多,直接在类内定义函数,函数加上前缀static即可。调用时还是通过类::静态函数调用
指向类的指针(称作指向对象的指针会更贴切)
一个指向 C++ 类的指针与指向结构的指针类似,访问指向类的指针的成员,需要使用成员访问运算符 ->(有的地方又叫指向运算符)。
.是成员运算符
与所有的指针一样,您必须在使用指针之前,对指针进行初始化。
#include <iostream>using namespace std;class Box{public:// 构造函数定义Box(double l=2.0, double b=2.0, double h=2.0){cout <<"Constructor called." << endl;length = l;breadth = b;height = h;}double Volume(){return length * breadth * height;}private:double length; // Length of a boxdouble breadth; // Breadth of a boxdouble height; // Height of a box};int main(void){Box Box1(3.3, 1.2, 1.5); // Declare box1Box Box2(8.5, 6.0, 2.0); // Declare box2Box *ptrBox; // Declare pointer to a class.//声明指向Box类类型的指针// 保存第一个对象的地址ptrBox = &Box1;// 现在尝试使用成员访问运算符来访问成员cout << "Volume of Box1: " << ptrBox->Volume() << endl;//相当于Box1.Volume()// 保存第二个对象的地址ptrBox = &Box2;// 现在尝试使用成员访问运算符来访问成员cout << "Volume of Box2: " << ptrBox->Volume() << endl;return 0;}当上面的代码被编译和执行时,它会产生下列结果:Constructor called.Constructor called.Volume of Box1: 5.94Volume of Box2: 102
类类型的指针初始化为某个对象,使用 指针->?即相当于该指针对象调用?成员
