C++ 从 base class 中的非虚函数调用纯虚函数
C++ calling pure virtual function from non virtual function in base class
我知道您可以/不应该在构造函数中调用虚函数,并且不可能使用纯虚析构函数。
我有两个 classes,Base 和 Child。
Base有一个纯虚函数和一个调用虚函数的普通函数。
// base.h
class Base {
public:
virtual int foo() const = 0;
int bar() const;
};
// base.cpp
#include "base.h"
int Base::bar() const {
return this->foo()*3;
}
Child实现了虚函数。
// child.h
#include "base.h"
class Child : public Base {
public:
int foo() const;
};
// child.cpp
#include "child.h"
int Child::foo() const {
return 5;
}
然后我创建 child object 并调用在基础中定义的 bar。
// main.cpp
#include "child.h"
...
Child c;
std::cout << c.bar();
...
clang 编译器然后给我一个链接器错误
Undefined symbols for architecture x86_64:
"Base::bar() const", referenced from:
_main in main.cpp.o
"vtable for Child", referenced from:
Child::Child() in main.cpp.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
这对我来说没有意义,因为据我所知,child class 定义了一个纯虚成员函数 foo。据我所知,bar 没有标记为虚拟,因此应该定义一个符号。是否以某种方式传递虚拟?
我哪里错了?
编辑:
这是我的 CMakeLists.txt
cmake_minimum_required(VERSION 3.6)
project(inheritance)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES main.cpp)
add_executable(inheritance ${SOURCE_FILES})
编辑 2:解决方案
根据@dasblinkenlight 的回答,源文件必须一起编译,因此最后一个代码块的第 6 行必须更改为
set(SOURCE_FILES main.cpp base.cpp child.cpp)
你打错了,Base::bar函数中遗漏了"const",然后它与Base class中声明的函数签名不同。
// base.cpp
int Base::bar() const {
return this->foo()*3;
}
I am aware that you can / should not call virtual functions in the constructor and that a pure virtual destructor is not possible.
声明一个函数纯虚并不意味着你不能为它提供一个实现。这也适用于析构函数:
struct Foo {
virtual ~Foo() = 0;
...
};
Foo::~Foo() {
... // Implement destructor
}
The clang compiler then gives me a linker error
Undefined symbols for architecture x86_64:
"Base::bar() const", referenced from:
这通常发生在您错误地编译 类 one-by-one,然后又没有正确地 link 时。编译器有一个简单的方法,将所有类编译在一起,并得到link的结果,如下:
g++ base.cpp child.cpp main.cpp
请注意,您需要在其实现文件中为 类 添加 headers,例如
#include "base.h"
int Base::bar() {
return this->foo()*3;
}
确保修复过程中出现的任何错误(提示:以上内容会产生错误)。
我知道您可以/不应该在构造函数中调用虚函数,并且不可能使用纯虚析构函数。
我有两个 classes,Base 和 Child。
Base有一个纯虚函数和一个调用虚函数的普通函数。
// base.h
class Base {
public:
virtual int foo() const = 0;
int bar() const;
};
// base.cpp
#include "base.h"
int Base::bar() const {
return this->foo()*3;
}
Child实现了虚函数。
// child.h
#include "base.h"
class Child : public Base {
public:
int foo() const;
};
// child.cpp
#include "child.h"
int Child::foo() const {
return 5;
}
然后我创建 child object 并调用在基础中定义的 bar。
// main.cpp
#include "child.h"
...
Child c;
std::cout << c.bar();
...
clang 编译器然后给我一个链接器错误
Undefined symbols for architecture x86_64:
"Base::bar() const", referenced from:
_main in main.cpp.o
"vtable for Child", referenced from:
Child::Child() in main.cpp.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
这对我来说没有意义,因为据我所知,child class 定义了一个纯虚成员函数 foo。据我所知,bar 没有标记为虚拟,因此应该定义一个符号。是否以某种方式传递虚拟?
我哪里错了?
编辑: 这是我的 CMakeLists.txt
cmake_minimum_required(VERSION 3.6)
project(inheritance)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES main.cpp)
add_executable(inheritance ${SOURCE_FILES})
编辑 2:解决方案 根据@dasblinkenlight 的回答,源文件必须一起编译,因此最后一个代码块的第 6 行必须更改为
set(SOURCE_FILES main.cpp base.cpp child.cpp)
你打错了,Base::bar函数中遗漏了"const",然后它与Base class中声明的函数签名不同。
// base.cpp
int Base::bar() const {
return this->foo()*3;
}
I am aware that you can / should not call virtual functions in the constructor and that a pure virtual destructor is not possible.
声明一个函数纯虚并不意味着你不能为它提供一个实现。这也适用于析构函数:
struct Foo {
virtual ~Foo() = 0;
...
};
Foo::~Foo() {
... // Implement destructor
}
The clang compiler then gives me a linker error
Undefined symbols for architecture x86_64: "Base::bar() const", referenced from:
这通常发生在您错误地编译 类 one-by-one,然后又没有正确地 link 时。编译器有一个简单的方法,将所有类编译在一起,并得到link的结果,如下:
g++ base.cpp child.cpp main.cpp
请注意,您需要在其实现文件中为 类 添加 headers,例如
#include "base.h"
int Base::bar() {
return this->foo()*3;
}
确保修复过程中出现的任何错误(提示:以上内容会产生错误)。