我应该使用前向声明来打破 C++ 模块片段之间的循环依赖关系吗?

问题描述 投票:0回答:1

Visual Studio 2022 中的 C++ 模块可以处理前向声明吗?

以下代码具有循环依赖关系,我想使用前向声明来打破它,但编译器似乎无法识别它引用与完整类声明相同的类型,因此它无法编译。我是不是做错了什么?

主.cpp

import A;

int main()
{
    CB cb;
    CC cc;
    cc.MyFunc3(cb);
    return 0;
}

A.ixx

export module A;

export import :B;
export import :C;

A-B.ixx

export module A:B;

class CC;

export class CB {
public:
    void MyFunc(const CC& cc) const;
};

A-B.cpp

module A;
import :B;

import std;
import :C;

void CB::MyFunc(const CC& cc)
{
    std::cout << "Hello World B" << std::endl;
}

A-C.ixx

export module A:C;

class CB;

export class CC {
public:
    void MyFunc1(const CB& cb) const;
};

A-C.cpp

module A;
import :C;

import std;
import :B;

void CC::MyFunc1(const CB& cb)
{
    std::cout << "Hello World B" << std::endl;
    cb.MyFunc(*this);
}

这是错误:

1>C:\Users\peterB\repositories\hobby projecten\Hexanaut-AI\Hexanaut-AI\Hexanaut-AI\A-C.cpp(7,10): error C2511: 'void CC::MyFunc1(const CB &)': overloaded member function not found in 'CC'
1>C:\Users\peterB\repositories\hobby projecten\Hexanaut-AI\Hexanaut-AI\Hexanaut-AI\A-C.ixx(5,14):
1>see declaration of 'CC'
1>C:\Users\peterB\repositories\hobby projecten\Hexanaut-AI\Hexanaut-AI\Hexanaut-AI\A-C.cpp(10,5): error C2027: use of undefined type 'CB'
1>C:\Users\peterB\repositories\hobby projecten\Hexanaut-AI\Hexanaut-AI\Hexanaut-AI\A-C.ixx(3,7):
1>see declaration of 'CB'
1>C:\Users\peterB\repositories\hobby projecten\Hexanaut-AI\Hexanaut-AI\Hexanaut-AI\A-C.cpp(10,16): error C2671: 'CC::MyFunc1': static member functions do not have 'this' pointers

相关编译器选项:

/std:c++latest /experimental:module

打开“构建 ISO C++23 标准库模块”。

c++ visual-c++ c++20 c++-modules
1个回答
0
投票

您的

export
声明需要更加一致。这包括前向声明。

CC
BB
都应该是
export
ed。这意味着它们的前向声明应该also
exported

避免过度重复的一种方法是为所有其他分区导入的此类声明创建一个模块分区:

//A-fwd.ixx
export module A:fwd;

export class CB;
export class CC;

//A-B.ixx
export module A:B;

export import :fwd;

export class CB {...};

export
中的
A-B
不是必须的,但作为提醒还是不错的。
A-C.ixx
还应该导入
:fwd

请注意,我对标准的解读是,在编译模块时,它应该给出了编译错误

A
。该文件导入
A:B
,这将
CC
声明为未导出。当它导入声明它导出的
A:C
时,应该触发 [module.interface]/6:

如果 X 是由导出声明引入的,则实体 X 的重新声明将被隐式导出;否则不得出口。

“不得导出”翻译为“如果实体被重新声明为导出,则格式错误”。但 VC++ 显然没有这样做。

它确实会给出错误最终,但仅当您尝试使用它时。看,它似乎正在翻译您的代码,以便有两种名为

CB
的类型:导出的类型和非导出的类型。对象
cb
属于导出类型,但
CC::MyFunc3
使用的类型是非导出类型。由于它们是两种不同的类型,并且没有定义转换运算符,因此您会收到错误。

© www.soinside.com 2019 - 2024. All rights reserved.