设定:
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 $@
答案 0 :(得分:3)
您无法调用未定义的函数。 gcc告诉你的确如此。并且foo::B->b();
不是有效的C ++。它不能使用g++
或cl.exe
进行编译。
如果你写了
public:
void b() {}
它会起作用。
答案 1 :(得分:1)
C foo = new C();
foo->b();
这可能是错的,你可能想要:
C foo;
foo.b();
它应该可以工作,只要你得到的错误不是链接器错误(我不熟悉gcc套件)。如果它是链接器错误,则意味着您的函数没有正文,因此无需调用。
答案 2 :(得分:1)
我认为您发布的任何一个片段都不应该编译。
class C: public A, public B {
public
void c();
};
:
访问说明符后需要public
。
C foo = new C();
foo->b();
您正尝试从指向动态分配的C
对象的指针初始化C
。 .
not ->
是在对象类型上调用函数的正确运算符。 ->
仅用于指针类型(或具有重载->
运算符的对象)。
您需要以下内容:
C foo;
foo.b();
我不确定你所说的片段是如何实际编译的。
答案 3 :(得分:1)
您得到的错误是链接器错误,而不是编译器错误。这意味着您的代码编译 - 很好。链接器抱怨,因为它找不到函数的定义。该定义是否在不同的C ++文件中?也许有一个文件B.cpp包含:
#include "B.h"
void B::b() {
// do something nifty here
}
然后有一个单独的文件C.cpp,其中包含:
#include "C.h"
C *
func() {
C* foo = new C();
foo->b();
return foo;
}
如果您只编译C.cpp,例如:
g++ -Wall -Wextra C.cpp
然后你会看到你看到的链接器错误。
也许您想要进行部分编译,然后再链接所有.o文件?
g++ -Wall -Wextra -c C.cpp
或许您想将它们全部编译在一起并同时链接?
g++ -Wall -Wextra A.cpp B.cpp C.cpp
答案 4 :(得分:0)
Try this out :
C *foo = new C();
And where is the function definitions ??.
Explicit scope resolution is only necessary in this case:
class A {
public:
void fun(){};
};
class B {
public:
void fun(){};
};
class C : public A , public B
{
};
int main()
{
C c;
c.A::fun();
}