在之前的类和对象①、②、③、④篇中,详细讲解了类和对象的基本知识,本章为最终章,继续为大家介绍类和对象。
我们已知的,在C++中,有一种私有访问修饰符,用于限制类的成员只能在类的内部访问。私有成员对外部是不可见的,其他类或函数无法直接访问私有成员。但是我们已经做过重载操作符这个动作,某些操作符可能会需要访问类的私有成员,那么private限制符就阻挡了我们的脚步。
这个时候就可以用到友元来解决这一问题。友元关系是C++中一个神秘而又强大的特性。它就像是一扇隐藏的秘密门,让我们能够进入类的私有领域。
友元可以分为友元函数和友元类
友元函数:
在C++中,友元函数是一个被声明为类的友元的非成员函数。像它的名字一样,这意味着友元函数可以直接访问类的私有成员和保护成员,而不需要通过类的对象或成员函数来访问。
友元函数的声明通常放在类的定义中,并使用关键字friend
进行标记。这将告诉编译器该函数是类的友元函数,可以访问类的私有成员。也可以说它是定义在类外部的普通函数,不属于任何类,但需要在
类的内部声明。
以下是友元函数的基本语法:
class MyClass {
private:
int privateVariable;
public:
friend void friendFunction();
};
在上述示例中,friendFunction()被声明为MyClass的友元函数
所以对友元函数做一个总结:
总而言之,将函数声明为类的友元函数的情况通常涉及到需要访问类的私有成员的操作,如重载操作符或优化性能。友元函数的存在打破了类的封装性,因此应该谨慎使用,并仅在确实需要访问私有成员时使用。
友元类:
友元类是也是C++中的一个特性,它允许一个类的所有成员函数或另一个类访问另一个类的私有成员和保护成员。通过将一个类声明为另一个类的友元类,可以打破类的封装性,并允许对私有成员的直接访问。
要将一个类声明为另一个类的友元类,也可以在被访问的类的定义中使用friend
关键字来声明友元类。
以下是友元类的基本语法:
class MyClass {
private:
int privateVariable;
public:
friend class FriendClass;
};
在上述示例中,
FriendClass
被声明为MyClass
的友元类。
通过友元类,友元类中的所有成员函数都可以直接访问被访问类的私有成员和保护成员。:
class MyClass {
private:
int privateVariable;
public:
friend class FriendClass;
};
class FriendClass {
public:
void accessPrivateMember(const MyClass& obj) {
int value = obj.privateVariable; // 可以访问私有成员
}
};
在上面的例子中,FriendClass是MyClass的友元类。在FriendClass的成员函数accessPrivateMember()中,可以直接访问MyClass的私有成员privateVariable。
需要注意的是,友元关系不具有传递性。如果类A是类B的友元类,类B不一定是类A的友元类。这意味着,虽然类A可以访问类B的私有成员,但类B不能直接访问类A的私有成员。
使用友元类需要谨慎考虑,因为它会打破类的封装性。友元类应该仅在确实需要对另一个类的私有成员进行直接访问时使用。
内部类是C++的另一个特性,它允许在一个类的内部定义另一个类。内部类可以访问包含它的外部类的所有成员,包括私有成员和保护成员。使用内部类可以将相关的类组合在一起,并提高代码的可读性和可维护性。
看如下代码:
class Class1 {
private:
int privateVariable;
public:
class InnerClass {
public:
void accessOuterMember(OuterClass& obj) {
int value = obj.privateVariable; // 可以访问外部类的私有成员
}
};
};
在上述示例中,在Class1内又定义了一个名为InnerClass的内部类。在InnerClass的成员函数accessOuterMember()中,可以直接访问OuterClass的私有成员privateVariable。
需要注意的是,内部类的名称对外部世界是不可见的。如果你想从外部访问内部类,你必须使用外部类的名称来限定它。
使用内部类可以将相关的类组合在一起,并提高代码的可读性和可维护性。内部类可以访问外部类的私有成员和保护成员,从而进一步增强了封装性。
在C++中,匿名对象是指没有命名的临时对象。它们通常在函数调用中使用,可以方便地创建一个临时对象并立即使用它,而不需要在代码中为它定义一个变量名。匿名对象可以作为函数的参数或返回值。
#include <iostream>
class MyClass {
public:
void print() {
std::cout << "Hello, World!\n";
}
};
int main() {
// 创建一个匿名对象,并立即调用它的成员函数
MyClass().print();
return 0;
}
在上面的代码中,我们创建了一个MyClass
的匿名对象,并立即调用它的成员函数print()
。由于这个对象没有被命名,因此我们不能在后面的代码中再次引用它。
在某些情况下,匿名对象可以提高代码的可读性和简洁性。例如,在创建临时对象时,我们可以使用匿名对象来避免创建不必要的变量。
需要注意的是,匿名对象的生命周期很短,只能在表达式中使用。当包含匿名对象的表达式结束时,匿名对象就会被销毁。