【问题标题】:Base and derived class in one header一个标头中的基类和派生类
【发布时间】:2013-11-13 12:55:20
【问题描述】:

我想把两个类放在一个头文件中。一个是基类,第二个是从这个基类派生的,我的意思是这样的:

class Drawable{
public:

  Drawable();

  void setPosition(math::Vector3 position);

  void draw();

};

class Box: public Drawable{} ;

但我收到错误“未定义对 `Drawable::Drawable()' 的引用”。在源文件中我有:

class Drawable {
public:
    math::Vector3 position;
    math::Vector3 rotation;

    Drawable() {
        position = math::Vector3(1.0, 1.0, 1.0);
        rotation = math::Vector3(0.0, 0.0, 0.0);
    }

    void setPosition(math::Vector3 position) {
        this->position = position;
    }

    void draw() {
    }
};

class Box: public Drawable {
public:
    void draw() {

        glBegin(GL_TRIANGLES);
        drawPoint(this->position + math::Vector3(1.0f, 1.0f, 1.0f));
        drawPoint(this->position + math::Vector3(-1.0f, 1.0f, 1.0f));
        drawPoint(this->position + math::Vector3(-1.0f, 1.0f, 1.0f));

        drawPoint(this->position + math::Vector3(1.0f, 1.0f, 1.0f));
        drawPoint(this->position + math::Vector3(1.0f, 1.0f, -1.0f));
        drawPoint(this->position + math::Vector3(1.0f, -1.0f, 1.0f));
        glEnd();
    }
};

所以在我看来这是不可能的,因为头文件中的派生类还不知道基类的构造函数。我说的对吗?

【问题讨论】:

    标签: c++ oop inheritance


    【解决方案1】:

    你需要做这样的事情:

    example.h

    class Drawable 
    { 
        public:
    
        Drawable();
    
        void setPosition(math::Vector3 position);
    
        virtual void draw();
    
        math::Vector3 position;
        math::Vector3 rotation;
    };
    
    class Box: public Drawable
    {
        public:
        virtual void draw();
    };
    

    example.cpp

    #include "example.h"
    
    Drawable::Drawable() {
        position = math::Vector3(1.0, 1.0, 1.0);
        rotation = math::Vector3(0.0, 0.0, 0.0);
    }
    
    void Drawable::setPosition(math::Vector3 position) {
        this->position = position;
    }
    
    void Drawable::draw() {
    }
    
    void Box::draw() {
    
        glBegin(GL_TRIANGLES);
        drawPoint(this->position + math::Vector3(1.0f, 1.0f, 1.0f));
        drawPoint(this->position + math::Vector3(-1.0f, 1.0f, 1.0f));
        drawPoint(this->position + math::Vector3(-1.0f, 1.0f, 1.0f));
    
        drawPoint(this->position + math::Vector3(1.0f, 1.0f, 1.0f));
        drawPoint(this->position + math::Vector3(1.0f, 1.0f, -1.0f));
        drawPoint(this->position + math::Vector3(1.0f, -1.0f, 1.0f));
        glEnd();
    }
    

    标题定义:

    • 构造函数/析构函数签名
    • 成员变量
    • 成员函数签名

    来源定义

    • 构造函数/析构函数实现
    • 会员功能实现

    注意:使用范围解析运算符:: 来引用类成员。

    【讨论】:

    • 在基类中有 draw 的空定义而不是 virtual 没有多大意义。
    • @KirilKirov 我刚刚回答了这个问题,实施不关我的事。
    • 抽奖将是虚拟的,这在当前点并不重要
    • @lukasz1985 将draw() 更新为virtual
    • 谢谢,这行得通。我试图按照我的方式去做。我只是习惯于 Java 语法,所有方法和数据成员都在类体内。我发现用 C++ 做同样的事情是不可能的。
    【解决方案2】:
    1. 所有数据成员(如math::Vector3 position;)必须仅在头文件中定义,而不是在 cpp 中。
    2. cpp文件中方法的定义为:return_type class_name::function_name (parameters) { ... }
    3. draw 在您的情况下应该是 virtual。甚至可能是纯虚拟的(如基类中的void draw() = 0;,并在派生类中声明和实现)。

    例子:

    ///////////////////////////////////////////
    // header
    class A
    {
    public:
        A();
        void f();
    private:
        int x;
    };
    
    /////////////////////////////////////////// 
    // cpp
    A::A() 
    { 
        /* constructor impl */ 
    }
    
    void A::f() 
    { 
        /* impl */ 
    }
    

    【讨论】:

      【解决方案3】:

      你可以像这样在源文件中实现你的方法:

      void Drawable :: setPositon(...){ //do stuff };
      

      您正在声明一个与标题中同名的新类!

      【讨论】:

        【解决方案4】:

        另外,鉴于您的 position 成员有一个 setter 函数,您可能应该将其设为私有,并声明和定义一个 getter:

        class Drawable{
        private:
            math::Vector3 position;
            math::Vector3 rotation;
        public:
            Drawable();
            void setPosition(math::Vector3 position);
            math::Vector3 getPosition();
            void setRotation(math::Vector3 rotation);
            math::Vector3 getRotation();
            void draw();
        };
        

        在您当前的实现中,调用 setter 会有些多余,因为您可以直接访问成员而不是使用 setter 函数:

        Drawable d;
        d.position = math::Vector3(0,0,0);      //both do the
        d.setPosition(math::Vector3(0,0,0));    //same thing
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-10-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多