文章目录
前言:
C++是一种面向对象的编程语言,允许程序员定义自己的类并在其中定义成员函数和变量。Friend关键字是一个强大的C++特性,它允许我们将一个函数或一个类声明为另一个类的Friend,从而使这个函数或类能够访问Friend类的private和protected成员。
本篇博客将探讨C++中Friend关键字的用法和基本原理,并以友元类的实现为例,进一步介绍如何使用Friend关键字的高级应用。
1. 友元
1.1 什么是友元?
在C++中,友元关键字用于指定一个函数或类可以访问另一个类中的私有和保护成员。友元向该类授予了访问控制权限,这种权限控制方式引入了一些新的细节,因为它不再是基于访问修饰符的简单访问控制。
友元可以是一个函数,也可以是一个类。友元函数是指一个函数能够直接和特定类的私有成员配对,从而获得它们的访问权限。类的友元是指一个类能够直接访问另一个类的私有成员,从而获得其访问权限。
友元的作用是提高程序的可用性和可维护性。在某些情况下,我们需要访问属于不同类的方法和变量。在这种情况下,通过使用友元,我们可以访问另一个类中的私有成员数据而不必公开访问它。总之,友元可以在保留信息封装的情况下,增强程序的可用性。
1.2 友元函数的实现
下面我们来看一下友元函数如何实现。首先,我们需要定义一个类,并声明一个友元函数。在这个例子中,我们定义了一个名为"CRectangle"的类,并声明了一个名为"printWidth"和"printHeight"的友元函数。
示例代码如下:
#include <iostream>
using namespace std;
class CRectangle {
friend int printWidth(CRectangle);
friend int printHeight(CRectangle);
private:
int width, height;
public:
void set_values(int,int);
};
void CRectangle::set_values(int x, int y) {
width = x;
height = y;
}
int printWidth(CRectangle rect) {
return rect.width;
}
int printHeight(CRectangle rect) {
return rect.height;
}
int main(){
CRectangle rect;
rect.set_values(3,4);
cout << "width:"<< printWidth(rect) << endl;
cout << "height:"<< printHeight(rect) << endl;
return 0;
}
在上面的程序中,友元函数"printWidth"和"printHeight"通过将对象或指针作为参数来访问类的成员变量。可以在类中定义非静态的友元函数,但是我们必须在类外部定义它。
以下是友元函数的特性:
-
友元函数可以访问类的非公共(private或protected)成员
-
友元不是类的成员
-
友元不受类访问控制符的影响
1.3 友元类的实现
友元类的使用场景相对友元函数更加广泛,下面我们来看一下友元类的实现。
首先,我们需要定义两个类,它们之间都会相互访问私有成员。在这个例子中,我们定义了两个类CBox和CTop,CBox中的私有成员函数可以通过友元CTop来访问。我们可以看出,友元类通常用于解决两个类之间存在依赖关系的情况。
示例代码如下:
#include <iostream>
using namespace std;
class CTop {
friend class CBox;
public:
void printWidth( CBox box );
};
class CBox {
private:
int width;
public:
void setWidth( int wid );
friend void CTop::printWidth( CBox box );
};
void CBox::setWidth( int wid ) {
width = wid;
}
void CTop::printWidth( CBox box ) {
cout << "Width of box : " << box.width <<endl;
}
int main() {
CBox box;
box.setWidth(10);
CTop top;
top.printWidth(box);
return 0;
}
在上面的程序中,我们可以看到以下特点:
-
友元类的权限是在类内部开放出去的,并不是类外部直接访问
-
友元类对所在的类没有任何影响
-
友元类能够拥有so在类定义中定义的任何访问权限
通过上面的例子,我们可以更好地理解友元类的使用场景。
1.4 总结:
友元是C++语言中非常重要的特性之一,可以帮助我们在类中访问私有成员,并且在不破坏封装性的情况下,提高程序的可用性和可维护性。在具体实现方面,我们介绍了友元函数和友元类的实现方法,对友元的理解和掌握将会对我们的编程水平有所提高。
2 内部类
2.1 什么是内部类
内部类是在一个类的内部定义的另一个类。它们在编译时拥有相同的访问权限,并且内部类可以访问外部类的私有成员。
内部类通常被用于分组内部和外部类的相互影响,从而使程序结构更加清晰和易于维护。此外,内部类还可以实现一些高级特性,包括继承、多态和模板特化等。
2.2 内部类的语法格式
在 C++ 中,定义内部类的基本语法格式如下:
class OuterClass {
public:
// 外部类的公有成员...
protected:
// 外部类的保护成员...
private:
// 外部类的私有成员...
class InnerClass {
public:
// 内部类的公有成员...
protected:
// 内部类的保护成员...
private:
// 内部类的私有成员...
};
};
其中,InnerClass 就是定义的内部类。需要注意的是,这里的访问权限(public、protected、private)实际上是对于内部类而言的,而不是针对外部类。
2.3 内部类的访问权限
内部类在编译时将外部类的信息也作为其一部分进行了编译。因此,内部类可以访问外部类的所有成员,包括私有成员。而反过来,外部类只能访问内部类的公有成员。
此外,内部类还可以被声明为外部类的友元类,以获得更广泛的访问权限。这种情况下,内部类可以访问其它外部类的私有成员。
2.4 内部类的应用示例
内部类作为 C++ 中比较高级的特性,其灵活性和应用场景非常广泛。接下来,将通过一些示例进行说明。
- 内部类实现迭代器
内部类可以用于实现 C++ 中的迭代器。下面是一个使用内部类实现迭代器的示例代码:
class Container {
private:
int* data;
int size;
public:
Container(int* d, int s) : data(d), size(s) {}
class Iterator {
private:
int* ptr;
public:
Iterator(int* p) : ptr(p) {}
Iterator& operator++() { ptr++; return *this; }
bool operator!=(const Iterator& it) const { return ptr != it.ptr; }
int& operator*() { return *ptr; }
};
Iterator begin() { return Iterator(data); }
Iterator end() { return Iterator(data + size); }
};
int main() {
int data[] = { 1, 2, 3, 4, 5 };
Container c(data, 5);
for (Container::Iterator i = c.begin(); i != c.end(); ++i) {
std::cout << *i << std::endl;
}
return 0;
}
在代码中,内部类 Iterator 实现了迭代器的基本功能,包括前进、比较和取值。外部类 Container 则提供了存储数据的数组、数组大小以及两个迭代器的封装和管理。
2. 内部类实现非重载操作符
内部类还可以用于实现 C++ 中的非重载操作符。下面是一个使用内部类实现“小于”操作符的示例代码:
class Point {
private:
int x, y;
public:
Point(int x_, int y_) : x(x_), y(y_) {}
class LessThan {
public:
bool operator()(const Point& p1, const Point& p2) {
return (p1.x * p1.x + p1.y * p1.y) <
(p2.x * p2.x + p2.y * p2.y);
}
};
};
int main() {
std::vector<Point> points = { {1, 1}, {2, 2}, {3, 3} };
std::sort(points.begin(), points.end(), Point::LessThan());
for (auto& p : points) {
std::cout << "(" << p.x << ", " << p.y << ")\n";
}
return 0;
}
在代码中,内部类 LessThan 实现了“小于”操作符,该操作符比较了点到原点的距离的平方。通过使用 std::sort 函数和自定义的操作符,可以对点进行排序。
2.5 总结
通过本篇博客我们可以了解到 C++ 内部类的定义和语法格式,并通过示例代码展示了内部类的一些应用场景。需要注意的是,内部类虽然具有访问外部类所有成员的特性,但也存在一些潜在的问题和注意事项,比如内存管理等。因此,在实际编程中需要根据具体情况谨慎使用。