2010-11-21 55 views
4

嘿家伙。感谢点击。我正在努力与包括。基本上,我正在尝试创建一个模板类,其中有一个函数可以接受该模板的特定实例。我做了以下人为的例子来说明这一点。转发声明/包含模板类 - “不完整类型的无效使用”

比方说,我有一个标记有模板(通用)类型数据的个人世界。我有一个特定的个人,称为国王。所有的个人都应该能够在国王面前跪下。一般来说,个人可以被标记为任何东西。国王以数字标记(第一,第二位国王)。

的误差

g++ -g -O2 -Wall -Wno-sign-compare -Iinclude -DHAVE_CONFIG_H -c -o Individual.o Individual.cpp 
g++ -g -O2 -Wall -Wno-sign-compare -Iinclude -DHAVE_CONFIG_H -c -o King.o King.cpp 
In file included from King.h:3, 
       from King.cpp:2: 
Individual.h: In member function ‘void Individual<Data>::KneelBeforeTheKing(King*)’: 
Individual.h:21: error: invalid use of incomplete type ‘struct King’ 
Individual.h:2: error: forward declaration of ‘struct King’ 
make: *** [King.o] Error 1 

Individual.h(Individual.cpp为空)

//Individual.h 
#pragma once 
class King; 
#include "King.h" 
#include <cstdlib> 
#include <cstdio> 

template <typename Data> class Individual 
{ 
protected: 
    Data d; 

public: 

    void Breathe() 
    { 
     printf("Breathing...\n"); 
    }; 

    void KneelBeforeTheKing(King* king) 
    { 
     king->CommandToKneel(); 
     printf("Kneeling...\n"); 
    }; 

    Individual(Data a_d):d(a_d){}; 
}; 

King.h

//King.h 
#pragma once 
#include "Individual.h" 
#include <cstdlib> 
#include <cstdio> 

class King : public Individual<int> 
{ 
protected: 

    void CommandToKneel(); 

public: 

    King(int a_d): 
     Individual<int>(a_d) 
    { 
     printf("I am the No. %d King\n", d); 
    }; 
}; 

King.cpp

//King.cpp 
#include "King.h" 
#include <string> 

int main(int argc, char** argv) 
{ 
    Individual<std::string> person("Townsperson"); 
    King* king = new King(1); 
    king->Breathe(); 
    person.Breathe(); 
    person.KneelBeforeTheKing(king); 

} 

void King::CommandToKneel() 
{ 
    printf("Kneel before me!\n"); 
} 

的Makefile

CXX = g++ 
CXXFLAGS = -g -O2 -Wall -Wno-sign-compare -Iinclude -DHAVE_CONFIG_H 
OBJS = Individual.o King.o 

test: $(OBJS) 
    $(CXX) -o [email protected] $^ 

clean: 
    rm -rf $(OBJS) test 

all: test 

回答

3

你的两个职业国王和个人是非常紧密耦合。

把它放在这样的两个头里是行不通的,因为两者都需要对方。

如果你的类必须被设计,然后这样:

  1. 首先定义类个人,但没有实现KneelBeforeTheKing,刚刚宣布的功能。

  2. 然后定义特大

  3. 然后实现上述方法。

但是,您的设计可能都是错误的。例如,您的模板类有很多不依赖于tamplated类型的方法,包括KneelBeforeTheKing,并且应该重新模板化。

+0

我在想我的设计是不正确的,因为我碰到的问题似乎有点人为的问题。我需要一个模板化的课程的原因是存储模板化的数据(一个国王被标记为第N个国王,一个人被标记为字符串作为他们的名字,另一种类型的人可以被标记为人的号码,即人# 234" )。有没有办法存储模板化的数据,而无需制作模板类? – SharkCop 2010-11-21 20:00:44

+0

@TheChariot:默认情况下(除非您在代码中声明)模板实例化是不相关的类。如果您有一个想要用语言表达的概念(“个人”),并且符合该概念的不同实体共享通用功能,请考虑使用继承。基类不会有任何存储的数据,每个派生类将添加特定的数据(一个普通人的字符串,一个未命名人员的数字......)在你的设计中,尽管他们共享一些方法,“Individual ”和'个人'不能通过相同的接口传递。 – 2010-11-22 09:00:33

3
error: invalid use of incomplete type ‘struct King’ 

这意味着,你只申报不King定义它。你有通告包括问题(Individual.hKing.h包括对方)。应该在这个问题上提出一些建议。

+0

只是为了让您知道,在gamedev.net文章的链接已损坏。文章似乎已被删除。 – 2011-09-25 20:54:13

+0

@Chris:谢谢,修正 – fredoverflow 2011-09-26 05:58:36

2

嗯,这里的问题与模板无关。

您正在调用基类中后代的特殊功能。这几乎总是一个糟糕的设计标志。

反转类怎么样?像这样的东西(可能有错误):

template < typename PersonType > 
class Person : PersonType 
{ 
    public: 
     void command_to_kneel() { PersonType::command_to_kneel(); } 
     void kneel_before_king(Person<King>* king) { king->command_to_kneel(); } 
     void breathe() { } 
}; 

int main() 
{ 
    Person<King> king; 
    Person<Knight> knight; 
    knight.kneel_before_king(&king); 
} 
+0

虽然在基类中调用后代通常是一种糟糕的设计,但错误并非如此。编译器抱怨'King'在实例化'Individual'时是不完整的,并且*对于调用派生方法的基类没有问题,但派生的方法在调用位置尚未定义。 – 2010-11-22 08:54:57

1

您可以通过添加另一个基类(例如NobleBase)对类国王打破依赖:

struct NobleBase 
{ 
    virtual void KneelBefore() = 0; 
}; 


class King : public Individual<int>, 
      public NobleBase 

,改变方法
void KneelBeforeTheKing(King* king)
这个
void KneelBeforeTheKing(NobleBase* king)

然后你需要包括头NobleBase类。

0

不考虑语法和编译器错误,我认为最大的问题是你的个人告诉国王告诉自己跪下。

void KneelBeforeTheKing(King* king) 
{ 
    king->CommandToKneel(); 
    printf("Kneeling...\n"); 
}; 

正如Let_Me_Be指出的那样,这是设计问题而不是语法问题。实际上,国王应该决定个人什么时候下跪,所以任何对CommandToKneel()的调用都来自国王本人,并且以一组个人作为论证来指定谁被指挥。

语法问题是您正在尝试使用尚未定义的功能。 King的所有前向声明都告诉Individual的头文件有一个称为King的类型。那时编译器对King的成员一无所知,因为你没有包含声明这些成员的头文件,也没有在King使用它之前将它定义在任何地方。然而,正如已经指出的那样,在其基本类型(即个体)的声明中对派生类型(即King)的任何类型的引用都是不好的设计。基类不应该知道它的派生类型。

相关问题