c++面向对象 之 基础 类修饰符 构造函数 友元函数
1,类和对象
定义一个类,本质上是定义一个数据类型的蓝图。这实际上并没有定义任何数据,但它定义了类的名称意味着什么,也就是说,它定义了类的对象包括了什么,以及可以在这个对象上执行哪些操作。
类定义格式如下:
class Box { public: //在类对象作用域内,公共成员在类的外部是可访问的。 double length; // 盒子的长度 double breadth; // 盒子的宽度 double height; // 盒子的高度 };
声明类对象:
Box Box1; // 声明 Box1,类型为 Box Box Box2; // 声明 Box2,类型为 Box
访问数据成员:
#include <iostream> using namespace std; class Box { public: double length; // 长度 double breadth; // 宽度 double height; // 高度 }; int main( ) { Box Box1; // 声明 Box1,类型为 Box Box Box2; // 声明 Box2,类型为 Box double volume = 0.0; // 用于存储体积 // box 1 详述 Box1.height = 5.0; //为实例的某个属性赋值,采用点号 Box1.length = 6.0; Box1.breadth = 7.0; // box 2 详述 Box2.height = 10.0; Box2.length = 12.0; Box2.breadth = 13.0; // box 1 的体积 volume = Box1.height * Box1.length * Box1.breadth; //访问某个实例的类中的某个属性,同样用点号,当然还要看共有还是私有 cout << "Box1 的体积:" << volume <<endl; // box 2 的体积 volume = Box2.height * Box2.length * Box2.breadth; cout << "Box2 的体积:" << volume <<endl; return 0; }
定义类成员函数:
内部定义成员函数:
class Box { public: double length; // 长度 double breadth; // 宽度 double height; // 高度 double getVolume(void) { return length * breadth * height; } };
外部定义成员函数,必须要使用范围解析运算符:
double Box::getVolume(void) //类名::函数名 { return length * breadth * height; }
在外部定义内联的成员函数,那么你需要一个关键字:inline
class A { public:void Foo(int x, int y) { } // 自动地成为内联函数 } // 头文件 class A { public: void Foo(int x, int y); } // 定义文件,这个也是内联函数,注意inline必须与函数定义放在一块 inline void A::Foo(int x, int y){}
调用成员函数:
#include <iostream> using namespace std; class Box { public: double length; // 长度 double breadth; // 宽度 double height; // 高度 // 成员函数声明 double getVolume(void); void setLength( double len ); void setBreadth( double bre ); void setHeight( double hei ); }; // 成员函数定义 double Box::getVolume(void) { return length * breadth * height; } void Box::setLength( double len ) { length = len; } void Box::setBreadth( double bre ) { breadth = bre; } void Box::setHeight( double hei ) { height = hei; } // 程序的主函数 int main( ) { Box Box1; // 声明 Box1,类型为 Box Box Box2; // 声明 Box2,类型为 Box double volume = 0.0; // 用于存储体积 // box 1 详述 Box1.setLength(6.0); Box1.setBreadth(7.0); Box1.setHeight(5.0); // box 2 详述 Box2.setLength(12.0); Box2.setBreadth(13.0); Box2.setHeight(10.0); // box 1 的体积 volume = Box1.getVolume(); cout << "Box1 的体积:" << volume <<endl; // box 2 的体积 volume = Box2.getVolume(); cout << "Box2 的体积:" << volume <<endl; return 0; }
2,类访问修饰符
class Base { public: // 公有成员, protected: // 受保护成员 private: // 私有成员 };
public:
#include <iostream> using namespace std; class Line { public: double length; void setLength( double len ); //声明成员函数 double getLength( void ); }; // 成员函数定义 double Line::getLength(void) //外部实现成员函数 { return length ; } void Line::setLength( double len ) { length = len; } // 程序的主函数 int main( ) { Line line; // 设置长度 line.setLength(6.0); //public支持使用类自带的成员函数修改属性值 cout << "Length of line : " << line.getLength() <<endl; //public同样支持在外部直接赋值类的属性 line.length = 10.0; // OK: 因为 length 是公有的 cout << "Length of line : " << line.length <<endl; return 0; }
private:
#include <iostream> using namespace std; class Box { public: double length; void setWidth( double wid ); double getWidth( void ); private: double width; }; // 成员函数定义,成员函数属于公有,但是操作的是私有的属性 double Box::getWidth(void) { return width ; } void Box::setWidth( double wid ) { width = wid; } // 程序的主函数 int main( ) { Box box; // 对于私有变量width来说,不使用成员函数设置宽度是不行的 // box.width = 10.0; // Error: 因为 width 是私有的 box.setWidth(10.0); // 只能使用成员函数设置宽度,也就是说私有的属性只有通过它自己定义的方法才能改变,外部不能改变它。 cout << "Width of box : " << box.getWidth() <<endl; return 0; }
protected:只有自己或者子类的成员函数才能访问
#include <iostream> using namespace std; class Box { protected: double width; }; class SmallBox:Box // SmallBox 是派生类 { public: void setSmallWidth( double wid ); double getSmallWidth( void ); }; // 子类的成员函数 double SmallBox::getSmallWidth(void) { return width ; } void SmallBox::setSmallWidth( double wid ) { width = wid; } // 程序的主函数 int main( ) { SmallBox box; // 使用成员函数设置宽度 box.setSmallWidth(5.0); cout << "Width of box : "<< box.getSmallWidth() << endl; return 0; }
-
1.private 成员只能被本类成员(类内)和友元访问,不能被派生类访问;
-
2.protected 成员可以被派生类访问。
3,构造函数和析构函数
构造函数:
c++中构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。
#include <iostream> using namespace std; class Line { public: void setLength( double len ); double getLength( void ); Line(); // 这是构造函数,构造函数里带参数也是可以的,就和普通函数带参数一样 private: double length; }; // 成员函数定义,包括构造函数 Line::Line(void) //定义构造函数,在class里直接定义也行。 { cout << "Object is being created" << endl; } void Line::setLength( double len ) { length = len; } double Line::getLength( void ) { return length; } // 程序的主函数 int main( ) { Line line; //一旦实例化就会跑构造函数 // 设置长度 line.setLength(6.0); cout << "Length of line : " << line.getLength() <<endl; return 0; }
构造函数可以用特殊的格式来初始化类内的某些属性:
Line::Line( double len): length(len) { 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) { .... }
析构函数:
类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。
析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。
#include <iostream> using namespace std; class Line { public: void setLength( double len ); double getLength( void ); Line(); // 这是构造函数声明 ~Line(); // 这是析构函数声明 private: double length; }; // 成员函数定义,包括构造函数 Line::Line(void) { cout << "Object is being created" << endl; } Line::~Line(void) { cout << "Object is being deleted" << endl; } void Line::setLength( double len ) { length = len; } double Line::getLength( void ) { return length; } // 程序的主函数 int main( ) { Line line; // 设置长度 line.setLength(6.0); cout << "Length of line : " << line.getLength() <<endl; //line.~Line(); 这样也是可以滴,手动析构以后系统还是会再检查一遍 return 0; }
4,拷贝构造函数
其实就是拷贝一个对象的实例,尽管听起来简单,但是拷贝的时候一定要注意指针或者引用等,小心语法错误
#include <iostream> //拷贝构造函数 using namespace std; class Line { public: int getLength( void ); Line( int len ); // 简单的构造函数 Line( const Line &obj); // 拷贝构造函数 ~Line(); // 析构函数 private: int *ptr; }; // 在对象的外部定义函数内容,成员函数定义,包括构造函数 Line::Line(int len) { cout << "调用构造函数" << endl; // 为指针分配内存 ptr = new int; //新建一个int数据类型 *ptr = len; } Line::Line(const Line &obj) //指明了要拷贝的是line这个对象,因为这个对象已经被构造过了 { cout << "调用拷贝构造函数并为指针 ptr 分配内存" << endl; ptr = new int; *ptr = *obj.ptr; //为啥是指针呢,因为ptr是个指针,相当于*(obj.ptr) } Line::~Line(void) { cout << "释放内存" << endl; delete ptr; } int Line::getLength( void ) { return *ptr; } void display(Line obj) { cout << "line 大小 : " << obj.getLength() <<endl; } // 程序的主函数 int main( ) { Line line(10); display(line); return 0; }
返回:
调用构造函数
调用拷贝构造函数并为指针 ptr 分配内存
line 大小 : 10
释放内存
释放内存
//函数声明等一致的情况下,拷贝构造函数也可以是直接复制实例 //接上一个函数 // 程序的主函数 int main( ) { Line line1(10); Line line2 = line1; // 这里也调用了拷贝构造函数 display(line1); display(line2); return 0; }
返回是这样的:
调用构造函数
调用拷贝构造函数并为指针 ptr 分配内存
调用拷贝构造函数并为指针 ptr 分配内存
line 大小 : 10
释放内存
调用拷贝构造函数并为指针 ptr 分配内存
line 大小 : 10
释放内存
释放内存
释放内存
5,友元函数
友元函数不是类的成员函数,而是定义在类的外部,但是又能访问私有和保护成员的函数,友元函数用friend指定。
class Box { double width; public: double length; friend void printWidth( Box box ); void setWidth( double wid ); };
#include <iostream> using namespace std; class Box { double width; public: friend void printWidth( Box box ); //注意此处的友元函数传递的参数是类实例哦。 void setWidth( double wid ); }; // 成员函数定义 void Box::setWidth( double wid ) { width = wid; } // 请注意:printWidth() 不是任何类的成员函数 void printWidth( Box box ) { /* 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员 */ cout << "Width of box : " << box.width <<endl; } // 程序的主函数 int main( ) { Box box; // 使用成员函数设置宽度 box.setWidth(10.0); // 使用友元函数输出宽度 printWidth( box ); return 0; }