友元、内部类、局部类
友元
友元包括友元函数和友元类
友元函数
举例来说,Point类描述了一个点的xy坐标,在另一个将两个点的横纵坐标相加而得到新的点的函数中,需要调用getX()和getY()来得到点的横纵坐标,因为m_x和m_y是private的不能外部访问。但这样的效率是不高的。每执行一次add就要执行四次get,四次栈空间的开辟和回收。
class Point {
private:
int m_x;
int m_y;
public:
int getX() {
return m_x;
};
int getY() {
return m_y;
};
Point(int x, int y) :m_x(x), m_y(y) {
}
void display() {
cout << "(" << m_x << ", " << m_y << ")" << endl;
}
};
Point add(Point p1, Point p2) {
return Point(p1.getX() + p2.getX(), p1.getY() + p2.getY());
}
解决方法:
-
将m_x和m_y公开,虽然说确实可以直接调用,但破坏了面向对象的封装性,也不好。
-
将add这个函数声明为Point类的友元函数,就允许add直接访问Point的私有成员变量。
class Point { friend Point add(Point, Point); private: int m_x; int m_y; public: int getX() { return m_x; }; int getY() { return m_y; }; Point(int x, int y) :m_x(x), m_y(y) { } void display() { cout << "(" << m_x << ", " << m_y << ")" << endl; } }; Point add(Point p1, Point p2) { return Point(p1.m_x + p2.m_x, p1.m_y + p2.m_y); }
如果将函数A(非成员函数)声明为类C的友元函数,那么在函数A内部就可以直接访问类C对象的所有成员。
友元类
比如创建一个Math类
class Point {
friend class Math;
private:
int m_x;
int m_y;
public:
int getX() {
return m_x;
};
int getY() {
return m_y;
};
Point(int x, int y) :m_x(x), m_y(y) {
}
void display() {
cout << "(" << m_x << ", " << m_y << ")" << endl;
}
};
class Math {
public:
Point add(Point p1, Point p2) {
return Point(p1.m_x + p2.m_x, p1.m_y + p2.m_y);
}
void test() {
Point p1(10, 20);
p1.m_x = 10;
p1.m_x;
}
};
那么Math中所有的成员函数都可以访问Point类的成员变量。
如果将类A声明为类C的友元类,那么在类A的所有成员函数内部都能直接访问类C对象的所有成员。
内部类
如果把类A定义在类C内部,类A就被称为内部类(嵌套类)
class Person {
private:
int m_age;
public:
class Car {
int m_price;
void run() {
Person person;
person.m_age = 10;
}
};
};
int main() {
Person::Car car1;
Person::Car car2;
getchar();
return 0;
}
内部类特点:
-
支持public、protected、private权限
-
成员函数可以直接访问其外部类对象的所有成员(反过来不行)
比如Person就是Car的外部类,可以在Car中创建Person对象然后访问Person的私有成员。
但Person里创建Car,并不能直接访问Car的私有成员。
-
成员函数可以直接不带类名、对象名访问其外部类的static成员
(本身static成员是需要通过类\对象\指针来访问的)
-
不会影响外部类的内存布局
person对象只占4个字节,只有一个m_age,Car对象里只有m_price
把Car写在里面还是外面内存布局不变,变的只有访问权限
-
可以在外部类内部声明,外部类外面定义
局部类
局部类:在一个函数内部定义的类,仅仅为这个函数服务
void test() {
static int age = 10;
// 局部类
class Car {
public:
void run() {
age = 20;
}
};
Car car;
car.run();
}
只有test内部能够访问,其他函数不能访问
-
特点
-
作用域仅限于所在的函数内部
-
其所有的成员必须定义在类内部,不允许定义static成员变量
因为static成员必须放在类外面初始化,但局部类所有东西都必须在函数内部,就矛盾了。
-
成员函数不能直接访问函数的局部变量(static变量除外)
-