代码之家  ›  专栏  ›  技术社区  ›  Chris Tonkinson

为什么需要明确的范围解析?

  •  1
  • Chris Tonkinson  · 技术社区  · 16 年前

    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没有类似签名的成员,所以我知道没有隐藏任何东西。两个问题:

    2) 在实践中,我可以做些什么来避免这种恼人的语法?

    干杯

    编辑: 抱歉,更新了示例代码-我的原始代码中存在一些错误类型。

    编辑2: 从src/biotel.h:

    #include "container.h"
    #include "identifiers.h"
    
    class Creature: public Identifiers, public Container {
      public:
        Creature( void );
        Creature( const Creature& ref );
        virtual ~Creature( void );
    };
    

    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;
    }
    

    笔记:

    2) 每个关联的对象文件都可以正常编译。只有链接器在链接所有对象文件的最后一步失败。

    3) GCC给出了:未定义的对“bioture::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 $@
    
    5 回复  |  直到 16 年前
        1
  •  1
  •   CB Bailey    16 年前

    我认为您发布的任何一个代码片段都不应该编译。

    class C: public A, public B {
      public
        void c();
    };
    

    : 之后 public 访问说明符。

    C foo = new C();
    foo->b();
    

    您正在尝试初始化一个 C C 对象 . -> 是对对象类型调用函数的正确运算符。 用于指针类型(或具有重载 -&燃气轮机;

    你需要像这样的东西:

    C foo;
    foo.b();
    

    我不确定你说的代码片段实际上是如何编译的。

        2
  •  3
  •   Alex Budovski    16 年前

    不能调用未定义的函数。gcc正是这么告诉你的。及 foo::B->b(); g++ cl.exe .

    如果你写

    public:
      void b() {}
    

    这会奏效的。

        3
  •  1
  •   user229321    16 年前
    C foo = new C();
    foo->b();
    

    这是错误的,您可能想要:

    C foo;
    foo.b();
    

    只要您得到的错误不是链接器错误(我不熟悉gcc套件),它就应该可以工作。如果是链接器错误,则意味着您的函数没有主体,因此没有可调用的内容。

        4
  •  1
  •   Dan    16 年前

    您得到的错误是链接器错误,而不是编译器错误。这意味着您的代码可以编译——很好。链接器正在抱怨,因为它找不到函数的定义。是在不同C++文件中的定义吗?可能有一个文件B.cpp包含:

    #include "B.h"
    void B::b() {
      // do something nifty here
    }
    

    #include "C.h"
    C *
    func() {
      C* foo = new C();
      foo->b();
      return foo;
    }
    

    如果只编译C.cpp,例如:

    g++ -Wall -Wextra C.cpp
    

    然后您将看到链接器错误。

    g++ -Wall -Wextra -c C.cpp
    

    g++ -Wall -Wextra A.cpp B.cpp C.cpp
    
        5
  •  0
  •   Ashish    16 年前
    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();
    
    }