C++ 和不完整的朋友 类
C++ and incomplete friend classes
我环顾四周,寻找 C++ 编译器中关于我所谓的假想朋友的选择背后的基本原理。不幸的是我没有找到任何解释所以我问专家。
我想知道为什么 C++ 不抱怨以下代码。 类 和方法表示朋友实际上并不存在,但如果您编译程序,它将编译并且 运行。
#include <iostream>
class TrueFriend
{
friend class NotExistingClass;
friend class AnotherNotExistingClass;
friend int NotExistingFunc();
public:
void TellAboutYou() { std::cout << "I have a lot of friends" << std::endl; }
};
int main(int argc, char **argv)
{
TrueFriend instance;
instance.TellAboutYou();
return 0;
}
I wondering why C++ does not complain about the following code.
C++ 是一种编程语言规范。
您可以阅读一些 C++ 标准,例如 n3337(或更新的标准)。该规范没有提到“投诉”。
GCC is a compiler implementing more or less C++. You could add your own GCC plugin 发出你想要的诊断。
这样的 GCC 插件会减慢编译速度。
您可以尝试使用 Clang static analyzer。由于它是开源的,因此您可以对其进行改进。
顺便说一句,当需要不存在的朋友 class 时,这是一个很好的情况。
您正在 不支持 OpenGL 的硬件上设计 GUI library (like FOX). In some cases, some widgets are not implemented (e.G. removed by some #ifdef HAVE_FOO_FEATURE
), but their class needs to be a friend of some existing class. Think for example of some sound related widget: on a PC without speakers, it makes no sense. Or think of some OpenGL 相关小部件。或者黑白屏幕上的一些彩色小部件....
或者您的 C++ 代码已被 GNU autoconf 配置。在某些情况下,某些 classes 会被禁用。
或者您正在编写一个库,与您的团队共同 决定未来 C++ class名为 NotExistingClass
,您负责实施的同事 John 正在休假、被分配到更紧急的工作或生病了。
同样,在某些 class WorkInProgessClass {
... }
中 声明 void some_missing_member_function()
并实现 WorkInProgessClass::some_missing_member_function
是合理的几周后,当你真正需要它的时候。
public APIs 应该比实现它们的代码更稳定。
理由是在一个团队开发的项目中,你想指定(在文档和stable头文件中)通用的API,并实现稍后。几个月后,您会发现根本不需要某些已定义和记录的函数。
一旦您团队中的伊莎贝尔(开发人员)使用 WorkInProgessClass::some_missing_member_function
,她将立即实施它(否则,linker 会抱怨)。同样,如果她声明一个转发的 class NotExistingClass
的对象,链接器会发出一些错误(可能:call/use 到未定义的 NotExistingClass::NotExistingClass()
构造函数...)
我喜欢编译 C++ 项目(比如 RefPerSys) with GCC 使用 g++ -Wall -Wextra -g
,如果收到你梦寐以求的警告,我会很生气。
另一个非常相关的示例缺少 virtual
方法(在某些抽象超级 class 中声明为 virtual void foo(void) =0;
),具体子 classes 在运行时从插件加载(在 Linux 上,使用 dlopen(3)...). AFAIK, Qt and FLTK 正在这样做。
没有理由使这段代码编译失败。友元声明足以声明类型。并且在您的代码中不需要定义。也许这样会更清楚:
class NotExistingClass;
class AnotherNotExistingClass;
int NotExistingFunc();
class TrueFriend
{
friend NotExistingClass;
friend AnotherNotExistingClass;
friend int NotExistingFunc();
public:
void TellAboutYou() { std::cout << "I have a lot of friends" << std::endl; }
};
效果相同:类和函数有声明但没有定义。在这里您可以了解前向声明的优点以及为什么有时需要它们:What are forward declarations in C++?
例如考虑两种类型 A
和 B
是共同的朋友。这是您需要前向声明的场景,因为 headers 不能相互包含:
// A.h
class B;
class A{ friend B;};
// B.h
#include "A.h"
class B{ friend A;};
A.h
的更短写法是
class A{ friend class B; };
现在假设您开始一个仅使用 A
但不使用 B
的新项目。你包括 A.h
,从不使用 B
,一切都很好。
PS:如评论中所述,friend
对于您的问题来说并不是真正必要的。声明但未定义类型和函数的情况并不少见,有时无法避免。
我环顾四周,寻找 C++ 编译器中关于我所谓的假想朋友的选择背后的基本原理。不幸的是我没有找到任何解释所以我问专家。
我想知道为什么 C++ 不抱怨以下代码。 类 和方法表示朋友实际上并不存在,但如果您编译程序,它将编译并且 运行。
#include <iostream>
class TrueFriend
{
friend class NotExistingClass;
friend class AnotherNotExistingClass;
friend int NotExistingFunc();
public:
void TellAboutYou() { std::cout << "I have a lot of friends" << std::endl; }
};
int main(int argc, char **argv)
{
TrueFriend instance;
instance.TellAboutYou();
return 0;
}
I wondering why C++ does not complain about the following code.
C++ 是一种编程语言规范。
您可以阅读一些 C++ 标准,例如 n3337(或更新的标准)。该规范没有提到“投诉”。
GCC is a compiler implementing more or less C++. You could add your own GCC plugin 发出你想要的诊断。
这样的 GCC 插件会减慢编译速度。
您可以尝试使用 Clang static analyzer。由于它是开源的,因此您可以对其进行改进。
顺便说一句,当需要不存在的朋友 class 时,这是一个很好的情况。
您正在 不支持 OpenGL 的硬件上设计 GUI library (like FOX). In some cases, some widgets are not implemented (e.G. removed by some #ifdef HAVE_FOO_FEATURE
), but their class needs to be a friend of some existing class. Think for example of some sound related widget: on a PC without speakers, it makes no sense. Or think of some OpenGL 相关小部件。或者黑白屏幕上的一些彩色小部件....
或者您的 C++ 代码已被 GNU autoconf 配置。在某些情况下,某些 classes 会被禁用。
或者您正在编写一个库,与您的团队共同 决定未来 C++ class名为 NotExistingClass
,您负责实施的同事 John 正在休假、被分配到更紧急的工作或生病了。
同样,在某些 class WorkInProgessClass {
... }
中 声明 void some_missing_member_function()
并实现 WorkInProgessClass::some_missing_member_function
是合理的几周后,当你真正需要它的时候。
public APIs 应该比实现它们的代码更稳定。
理由是在一个团队开发的项目中,你想指定(在文档和stable头文件中)通用的API,并实现稍后。几个月后,您会发现根本不需要某些已定义和记录的函数。
一旦您团队中的伊莎贝尔(开发人员)使用 WorkInProgessClass::some_missing_member_function
,她将立即实施它(否则,linker 会抱怨)。同样,如果她声明一个转发的 class NotExistingClass
的对象,链接器会发出一些错误(可能:call/use 到未定义的 NotExistingClass::NotExistingClass()
构造函数...)
我喜欢编译 C++ 项目(比如 RefPerSys) with GCC 使用 g++ -Wall -Wextra -g
,如果收到你梦寐以求的警告,我会很生气。
另一个非常相关的示例缺少 virtual
方法(在某些抽象超级 class 中声明为 virtual void foo(void) =0;
),具体子 classes 在运行时从插件加载(在 Linux 上,使用 dlopen(3)...). AFAIK, Qt and FLTK 正在这样做。
没有理由使这段代码编译失败。友元声明足以声明类型。并且在您的代码中不需要定义。也许这样会更清楚:
class NotExistingClass;
class AnotherNotExistingClass;
int NotExistingFunc();
class TrueFriend
{
friend NotExistingClass;
friend AnotherNotExistingClass;
friend int NotExistingFunc();
public:
void TellAboutYou() { std::cout << "I have a lot of friends" << std::endl; }
};
效果相同:类和函数有声明但没有定义。在这里您可以了解前向声明的优点以及为什么有时需要它们:What are forward declarations in C++?
例如考虑两种类型 A
和 B
是共同的朋友。这是您需要前向声明的场景,因为 headers 不能相互包含:
// A.h
class B;
class A{ friend B;};
// B.h
#include "A.h"
class B{ friend A;};
A.h
的更短写法是
class A{ friend class B; };
现在假设您开始一个仅使用 A
但不使用 B
的新项目。你包括 A.h
,从不使用 B
,一切都很好。
PS:如评论中所述,friend
对于您的问题来说并不是真正必要的。声明但未定义类型和函数的情况并不少见,有时无法避免。