C++20 模块“循环依赖”

问题描述

我试图在另一个模块中包含一个模块,但由于以下错误我无法编译:

“无法构建以下源文件,因为它们之间存在循环依赖:Module1.ixx 依赖 Module2.ixx 依赖 Module1.ixx。”

我想 modClass1_ 包含 modClass2_ 类并且 modClass2_ 包含一个指向静态 modClass1_ 的指针。


我使用 C++17 头文件和源文件(.h 和 .cpp)成功尝试的代码

// Class1.h
#pragma once
#include "Class2.h"
class modClass2_;
class modClass1_
{
public:
    modClass1_() {};
    ~modClass1_() {};
    int V = 2;
    int getV() { return V; };
    static modClass2_ mc2;
};
extern modClass1_ mc1;
// Class1.cpp
#include "Class1.h"
modClass1_ mc1;
modClass2_ modClass1_::mc2;
// Class2.h
#pragma once
#include "Class1.h"
class modClass2_
{
public:
    modClass2_() {};
    ~modClass2_() {};
    int V = 1;
    int getV() { return V; };
    int getClass1V();
};
// Class2.cpp
#include "Class2.h"
int modClass2_::getClass1V()
{
    return mc1.V;
}
// Main.cpp
#include "Class1.h"
#include <iostream>
int main()
{
    std::cout << mc1.getV() << "\n"; // gets modClass1_ V directly
    std::cout << mc1.mc2.getClass1V() << "\n"; // gets modClass1_ V through modClass2_ through modClass1_
    std::cout << mc1.mc2.getV() << "\n"; // gets modClass2_ V through modClass1_
}

我尝试过但使用 C++20 模块 (.ixx) 失败的代码

// Module1.ixx
export module Module1;
import Module2;
export class modClass1_
{
public:
    modClass1_() {};
    ~modClass1_() {};
    int getV() { return V; };
    modClass2_ mc2;
    int getModule2V() { return mc2.V; };
    int V = 1;
};
export modClass1_ mc1;
// Module2.ixx
export module Module2;
import Module1;
export class modClass2_
{
public:
    modClass2_() {};
    ~modClass2_() {};
    int getV() { return V; };
    int getModule1V() { return mc1.V; };
    int V = 2;
};

任何帮助/建议将不胜感激。

环境:Visual Studio 2019 | MSVC-2019 | C++20 | Windows 10 专业版

解决方法

就像头文件一样,您可以将模块接口文件与模块实现文件分开。示例:

Module1.ixx:

export module Module1;

import Module2;

export class modClass1_
{
public:
  modClass1_() {};
  ~modClass1_() {};
  int getV() { return V; };
  modClass2_ mc2;
  int getModule2V() { return mc2.V; };
  int V = 1;
};
export modClass1_ mc1;

Module2.ixx:

export module Module2;

export class modClass2_
{
public:
  modClass2_() {};
  ~modClass2_() {};
  int getV() { return V; };
  int getModule1V();
  int V = 2;
};

Module2.cpp:

import Module1;
import Module2;

int modClass2_::getModule1V()
{
  return mc1.V;
}

main.cpp:

#include <iostream>

import Module1;
import Module2;

int main()
{
  // NB: mc1 is a symbol imported from Module1
  std::cout << "mc1.V: " << mc1.V << '\n';
  std::cout << "mc1.getModule2V: " << mc1.getModule2V() << '\n';

  modClass2_ mc2;
  std::cout << "mc2.V: " << mc2.V << '\n';
  std::cout << "mc2.getModule1V: " << mc2.getModule1V() << '\n';
}

请注意,modClass2_ 的接口不需要来自 Module1 的任何内容,因此 Module2.ixx 没有 import Module1;Module2.cpp 是实现所在的位置。

在我的示例中,我尽可能少地从 Module2.ixx 移入 Module2.cpp 实现文件,但实际上您可能希望将更多内容移出界面。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...