【发布时间】:2010-12-25 13:19:21
【问题描述】:
设置:
class A {
public:
void a() {}
};
class B {
public:
void b() {}
};
class C: public A, public B {
public:
void c() {}
};
(我认为)我应该能够做什么:
C* foo = new C();
foo->b();
我从 GCC 收到以下链接器错误:
`... undefined reference to 'C::b(void)'`
如果我使用显式范围解析,它会起作用,如下所示:
C* foo = new C();
foo->B::b();
A、B 和 C 不共享具有相似签名的成员,所以我知道没有隐藏任何内容。两个问题:
1) 为什么理论上我不能隐式访问公共基类成员?
2) 在实践中我可以做些什么(如果有的话)来避免这种烦人的语法?
我可以继续使用显式语法进行开发(尽管我宁愿摆脱它),但我更希望在这里了解我(显然不正确)关于 C++ 中公共继承的知识。
干杯!
编辑:抱歉,更新了示例代码 - 我的原始代码中有一些严重的错误输入。
EDIT2:这是真实代码的(相关部分): 来自 src/creature.h:
#include "container.h"
#include "identifiers.h"
class Creature: public Identifiers, public Container {
public:
Creature( void );
Creature( const Creature& ref );
virtual ~Creature( void );
};
来自 src/identifier.h:
class Identifiers {
public:
Identifiers( void );
Identifiers( const Identifiers& ref );
~Identifiers( void );
};
来自 src/container.h:
class Container {
public:
Container( std::string (Object::*getName)( void ) const );
Container( const Container& ref );
~Container( void );
void add( Object* object );
void add( const std::list<Object*>& objects );
void remove( Object* object );
void remove( const std::list<Object*>& objects );
};
来自 src/container.cpp:
Container::Container( std::string (Object::*getName)( void ) const ) {
_getName = getName;
return;
}
Container::Container( const Container& ref ) {
_getName = ref._getName;
return;
}
Container::~Container( void ) {
while ( !objectList().empty() ) {
delete objectList().front();
objectList().pop_front();
}
return;
}
void Container::add( Object* object ) {
objectList().push_back( object );
return;
}
void Container::add( const std::list<Object*>& objects ) {
objectList().insert( objectList().end(), objects.begin(), objects.end() );
return;
}
void Container::remove( Object* object ) {
objectList().remove( object );
return;
}
void Container::remove( const std::list<Object*>& objects ) {
for ( std::list<Object*>::const_iterator it = objects.begin(); it != objects.end(); ++it ) {
remove( *it );
}
return;
}
来自应用程序本身:
bool CmdWear::execute( Creature* creature, const std::string& args ) {
std::list<Object*> objects;
Object* removed = NULL;
std::string error;
objects = creature->searchObjects( args );
for ( std::list<Object*>::iterator it = objects.begin(); it != objects.end(); ++it ) {
if ( creature->wear( *it, error, removed ) ) {
creature->remove( *it );
}
}
return true;
}
注意事项:
1) 此处显示的所有方法均在其相应的 .cpp 文件中定义。
2) 每个关联的目标文件都编译得很好。只有链接器在将所有目标文件链接在一起的最后一步失败。
3) GCC 吐出:对 `Creature::remove(Object*)' 的未定义引用,除非我通过以下方式明确限定范围:
creature->Container::remove( *it );
生成文件:
PROJECT = symphony
CPPC = g++
FLAGS_DEV = -ggdb3 -ansi -Wall -Werror -pedantic-errors
LIBS = `pcre-config --libs` `mysql_config --libs`
SRC_DIR = src
OBJ_DIR = obj
BIN_DIR = .
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
OBJ_FILES := $(patsubst src/%.cpp,obj/%.o,$(SRC_FILES))
dev: $(OBJ_FILES)
$(CPPC) $(LIBS) $(FLAGS_DEV) $(OBJ_FILES) -o $(BIN_DIR)/$(PROJECT)
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CPPC) -c $(FLAGS_DEV) $< -o $@
【问题讨论】:
-
Alex 下面的回答是正确的;但是,我认为您在编写此测试用例时遗漏了一些东西,并且您的真实代码可能正在做一些稍微不同的事情。 (由于您忘记将 'foo' 设为指针,因此引用的错误消息显然来自其他代码。)
-
我认为您遗漏了一些细节。 “C foo = 新 C();”单独应该不编译,因为 foo 需要是一个指针。
-
好吧,既然您已经更改(修复)了您的代码,它不再给出您声称的链接器错误。所以你的问题不再有意义。
-
请剪切并粘贴(不要重新输入)完整的代码来证明您的错误。
-
不需要真正的代码,只要最小的测试用例正确地演示了同样的问题。
标签: c++ inheritance gcc scope visibility