0

我现在已经将多态性与单个子类结合起来。如以下代码所示,其中两个函数 Draw() 和 SetValue(int,int,int) 导致链接器错误。

 #include "Header.h"

 class Object{
int tag;
 public:
void SetValues(int,int,int);
void Draw();
int getTag(){
    return tag;
}
 };
class Square: public Object{
int red;
int green;
int blue;
void Draw();
void SetValues(int red2,int green2, int blue2){
red=red2;
green=green2;
blue=blue2;
}
};
void Square::Draw(){
 // Draws a square with a gradient color at coordinates 0, 10
  glBegin(GL_QUADS);
  {
glColor3f(red, green, blue);
glVertex2i(1, 11);
glColor3f(red * .8, green * .8, blue * .8);
glVertex2i(-1, 11);
glColor3f(red * .5, green * .5, blue * .5);
glVertex2i(-1, 9);
glColor3f(red * .8, green * .8, blue * .8);
glVertex2i(1, 9);
  }
  glEnd();
}

错误

Error   1   error LNK2019: unresolved external symbol "public: void __cdecl Object::SetValues(int,int,int)" (?SetValues@Object@@QEAAXHHH@Z) referenced in function "public: void __cdecl State::DrawAll(void)" (?DrawAll@State@@QEAAXXZ)    C:\Users\Asher\documents\visual studio 2012\Projects\Procedural Terrain\Procedural Terrain\State.obj    Procedural Terrain
Error   2   error LNK2019: unresolved external symbol "public: void __cdecl Object::Draw(void)" (?Draw@Object@@QEAAXXZ) referenced in function "public: void __cdecl State::DrawAll(void)" (?DrawAll@State@@QEAAXXZ)    C:\Users\Asher\documents\visual studio 2012\Projects\Procedural Terrain\Procedural Terrain\State.obj    Procedural Terrain

在一个较大的类中,它不继承 Object 的函数,使用 DrawAll() 并在其中调用 Draw()。cpp文件和各自的两个头文件如下。

#include "Header.h"
#include "Object.h" 
float rotate_z=0;
class State{
private:
std::vector<Object> storage;
public:
State();
State Interpolate(State, State, double);
void Integrate(State,double, const double);
void DrawAll();
void AddObject(Object);
void RemoveObject(int);
};
State::State(){

}
State State::Interpolate(State current,State previous,const double alpha){
//current*alpha + previous * ( 1.0 - alpha );
return current;
}
void State::Integrate(State current, double t, const double dt){
}
void State::AddObject(Object object){
storage.push_back(object);
}
void State::RemoveObject(int tag){
//for(int i=0;i<storage.size;i++){
//  if(storage.at(i).getTag==tag){
//storage.erase(storage.begin()+i);
//  }
//}
}
void State::DrawAll(void)
{
  // reset view matrix
  glLoadIdentity();
// move view back a bit
glTranslatef(0, 0, -30);
// apply the current rotation

glRotatef(rotate_z, 0, 0, 1);
rotate_z += 5;
// by repeatedly rotating the view matrix during drawing, the
// squares end up in a circle
int i = 0, squares = 15;
float red = 0, blue = 1;
for (; i < squares; ++i){
  Square square;
Object * squareP=&square;
glRotatef(360.0/squares, 0, 0, 1);
// colors change for each square
red += 1.0/12;
blue -= 1.0/12;
squareP->SetValues(red,0.6,blue);
squareP->Draw();
  }
}

对象标题 -

#ifndef Object_H
#define Object_H

class Object{
int tag;

public:
void SetValues(int,int,int);
void Draw();
int getTag();
};
class Square: public Object{
int red;
int green;
int blue;
void Draw();
void SetValues(int red2,int green2, int blue2);
};
#endif

最后是状态标题 -

#ifndef State_H
#define State_H

#include "Object.h"
#include <vector>
class State{
private:
std::vector<Object> storage;
public:
State();
State Interpolate(State, State, double);
void Integrate(State,double, const double);
void DrawAll();
void AddObject(Object);
void RemoveObject(int);
};
#endif

这是我从事的第一个 C++ 项目,但尚未完全从 Java 背景转移。问题可能是什么?

4

2 回答 2

1

没有任何内容被标记为virtual,并且我看不到 Object::Draw() 或 Object::SetValues() 的任何实现。

In C++ to allow a subclass to override a function in the base class, it needs to be marked as virtual (in Java everything is always "virtual").

You can have "abstract" methods (like Java) by saying

class Object {
    public:
        virtual void SetValues(int,int,int) = 0;
于 2013-01-22T00:52:37.423 回答
1

Your Object class has no implementation of SetValues function. You may want a pure virtual function. Same for Draw.

class Object {
    virtual void SetValues(int,int,int) = 0;
}

Also note that in C++ functions are not virtual by default. You have to use the virtual keyword explicitly in the base class.

Also class Object seems to be defined at multiple places. Why? Defining it in Object.h would be sufficient.

Also please indent your code because it is very hard to read.

Also std::vector<Object> will not do what you want! Unline Java, where everything is a reference, in C++ things are stored by value in an std::vector and therefore your code is subject to the slicing problem. You want to use at lease a pointer there (std::vector<Object*>) but a smart pointer would be even better (std::vector<std::shared_ptr<Object>>)

于 2013-01-22T00:53:05.087 回答