小凯2013 发表于 2022-12-19 14:38:49

为什么老是报错?


DLL源代码(HomeWork.cpp, 自己写的):#include <iostream>
using namespace std;

#define DLLEXPORT __declspec(dllexport)

extern "C" class DLLEXPORT Lovers {
      public:
                Lovers(string name);
                void kiss(Lovers *lover);
                void ask(Lovers *lover, string something);

      protected:
                string name;

      friend class Others;
};

extern "C" class DLLEXPORT BoyFriend : public Lovers {
      public:
                BoyFriend(string name);
};

extern "C" class DLLEXPORT GirlFriend : public Lovers {
      public:
                GirlFriend(string name);
};

extern "C" class DLLEXPORT Others {
      public:
                Others(string name);
                void kiss(Lovers * lover);

      protected:
                string name;
};

extern "C" DLLEXPORT Lovers::Lovers(string name) {
      this->name = name;
}

extern "C" void DLLEXPORT Lovers::kiss(Lovers * lover) {
      cout << name << "亲亲我们家的" << lover->name << endl;
}

extern "C" void DLLEXPORT Lovers::ask(Lovers * lover, string something) {
      cout << "宝贝儿" << lover->name << "帮我" << something << endl;
}

extern "C" DLLEXPORT BoyFriend::BoyFriend(string name) : Lovers(name) {
}

extern "C" DLLEXPORT GirlFriend::GirlFriend(string name) : Lovers(name) {
}

extern "C" DLLEXPORT Others::Others(string name) {
      this->name = name;
}
编译命令:cl HomeWork.cpp /LD
(CL编译器,Version19.34.31937 x64 Microsoft优化版)


主程序代码(main.cpp):
#include <iostream>
using namespace std;

extern class Lovers;
extern class BoyFriend;
extern class GirlFriend;
extern class Others;

int main(void) {
      string boyName, girlName;

      cout << "请输入新郎姓名:";
      cin >> boyName;
      cout << "请输入新娘姓名:";
      cin >> girlName;

      BoyFriend boyFriend(boyName);
      GirlFriend girlFriend(girlName);
      Others others("路人甲");

      girlFriend.kiss(&boyFriend);
      boyFriend.kiss(&girlFriend);
      girlFriend.ask(&boyFriend, "洗衣服啦");

      cout << endl << "当当当当!传说中的路人甲登场!" << endl;
      others.kiss(&girlFriend);

      return 0;
}


编译命令:cl main.cpp /link HomeWork.lib
(CL编译器,Version 19.34.31937 x64 Microsoft优化版)

错误信息:
用于 x64 的 Microsoft (R) C/C++ 优化编译器 19.34.31937 版
版权所有(C) Microsoft Corporation。保留所有权利。

main.cpp
main.cpp(4): warning C4091: “extern ”: 没有声明变量时忽略“Lovers”的左侧
main.cpp(5): warning C4091: “extern ”: 没有声明变量时忽略“BoyFriend”的左侧
main.cpp(6): warning C4091: “extern ”: 没有声明变量时忽略“GirlFriend”的左侧
main.cpp(7): warning C4091: “extern ”: 没有声明变量时忽略“Others”的左侧
main.cpp(17): error C2079: “boyFriend”使用未定义的 class“BoyFriend”
main.cpp(17): error C2440: “初始化”: 无法从“std::string”转换为“int”
main.cpp(17): note: 没有可用于执行该转换的用户定义的转换运算符,或者无法调用该运算符
main.cpp(18): error C2079: “girlFriend”使用未定义的 class“GirlFriend”
main.cpp(18): error C2440: “初始化”: 无法从“std::string”转换为“int”
main.cpp(18): note: 没有可用于执行该转换的用户定义的转换运算符,或者无法调用该运算符
main.cpp(19): error C2079: “others”使用未定义的 class“Others”
main.cpp(19): error C2440: “初始化”: 无法从“const char ”转换为“int”
main.cpp(19): note: 没有使该转换得以执行的上下文

求助!!!



zhangjinxuan 发表于 2022-12-19 14:38:50

两个问题:
1. extern 只能是函数或变量,不能是类,我觉得你应该把 homework.cpp 做成头文件,也就是 hpp,当然这没什么必要,都是一样的效果
main 中就 include 一下 homework.cpp,记得要用 ""

所以,homework.cpp 内容:
#include <iostream>
using namespace std;

#define DLLEXPORT __declspec(dllexport)

extern "C" class DLLEXPORT Lovers {
      public:
                Lovers(string name);
                void kiss(Lovers *lover);
                void ask(Lovers *lover, string something);

      protected:
                string name;

      friend class Others;
};

extern "C" class DLLEXPORT BoyFriend : public Lovers {
      public:
                BoyFriend(string name);
};

extern "C" class DLLEXPORT GirlFriend : public Lovers {
      public:
                GirlFriend(string name);
};

extern "C" class DLLEXPORT Others {
      public:
                Others(string name);
                void kiss(Lovers * lover);

      protected:
                string name;
};

extern "C" DLLEXPORT Lovers::Lovers(string name) {
      this->name = name;
}

extern "C" void DLLEXPORT Lovers::kiss(Lovers * lover) {
      cout << name << "亲亲我们家的" << lover->name << endl;
}

extern "C" void DLLEXPORT Lovers::ask(Lovers * lover, string something) {
      cout << "宝贝儿" << lover->name << "帮我" << something << endl;
}

extern "C" DLLEXPORT BoyFriend::BoyFriend(string name) : Lovers(name) {
}

extern "C" DLLEXPORT GirlFriend::GirlFriend(string name) : Lovers(name) {
}

extern "C" DLLEXPORT Others::Others(string name) {
      this->name = name;
}
main.cpp 内容:
#include "homework.cpp"

int main(void) {
      string boyName, girlName;

      cout << "请输入新郎姓名:";
      cin >> boyName;
      cout << "请输入新娘姓名:";
      cin >> girlName;

      BoyFriend boyFriend(boyName);
      GirlFriend girlFriend(girlName);
      Others others("路人甲");

      girlFriend.kiss(&boyFriend);
      boyFriend.kiss(&girlFriend);
      girlFriend.ask(&boyFriend, "洗衣服啦");

      cout << endl << "当当当当!传说中的路人甲登场!" << endl;
      others.kiss(&girlFriend);

      return 0;
}

要注意,homework 已经导入了 iostream,已经 using 了 std,所以 main.cpp 再导入 iostream 没有必要

2. Other::kiss 仅声明了但没有定义

小凯2013 发表于 2022-12-19 14:40:18

在线等急!!!

高山 发表于 2022-12-20 08:05:48

@zhangjinxuan

zhangjinxuan 发表于 2022-12-20 08:10:13

好,我来研究研究

dolly_yos2 发表于 2022-12-20 10:11:06

能不能说明一下这是在做什么?
出现错误的原因在于编译器在编译 main.cpp 的时候对于另一个 cpp 文件中的内容,具体的,这些自定义的类的信息,包括它们的成员变量、方法等,一无所知,它只能假设它们的构造函数接受 int 型变量作为参数,因此提示无法从 std::string 转换到 int 。
需要让编译器知道这些类型的具体信息。可能将类的声明放在头文件中供两个 cpp 文件引用,将类方法等的实现放在 HomeWork.cpp 中,将 HomeWork.cpp 编译为库并将其链接到主程序上会是比较常见的方案。
5楼的方法应该能够工作,但多少有点邪道的意味在里面
另外,就像5楼提到的, Other::kiss 没有实现,因此即使正确组织应该也无法工作。

zhangjinxuan 发表于 2022-12-21 08:58:24

dolly_yos2 发表于 2022-12-20 10:11
能不能说明一下这是在做什么?
出现错误的原因在于编译器在编译 main.cpp 的时候对于另一个 cpp 文件中的 ...

哪里邪道了{:10_277:}

dolly_yos2 发表于 2022-12-21 10:44:01

zhangjinxuan 发表于 2022-12-21 08:58
哪里邪道了

这么做和把所有内容写到一个文件里没有区别,既然如此何必拆分成不同的文件呢?
这种方式,如果不小心进行的话,还可能带来各种问题,比如符号的多重定义。逻辑上这种拆分文件的组织方式是尤其为了服务大规模的代码的,但随意 include 源文件会抵消甚至逆转其带来的好处

zhangjinxuan 发表于 2022-12-21 10:45:14

dolly_yos2 发表于 2022-12-21 10:44
这么做和把所有内容写到一个文件里没有区别,既然如此何必拆分成不同的文件呢?
这种方式,如果不小心进 ...

有道理,学会了,感谢大佬提醒

zhangjinxuan 发表于 2022-12-21 10:46:08

你的头像,不拿CCF一等奖???{:10_277:}
页: [1]
查看完整版本: 为什么老是报错?