2013-01-04 5 views
4

이는 에러이다잘못 초기화 : 벡터

DummyService.hpp:35: error: invalid covariant return type for 'virtual std::vector < ResourceBean*, std::allocator < ResourceBean*> >& DummyService::list(const std::string&)'

class Bean { 
public: 
    typedef std::string Path; 
    virtual ~Bean() {}; 
    virtual const Path& getPath() = 0; 
    virtual const std::string& getName() = 0; 
protected: 
    Bean(); 
}; 

class ResourceBean: public Bean { 
public: 
    ResourceBean(const Path& path, const std::string& contents) : 
      _path(path), _contents(contents) { 
    } 
    virtual ~ResourceBean() { } 
    virtual const Path& getPath(); 
    virtual void setPath(const Path& path); 
    virtual const std::string& getName(); 
    virtual void setName(const std::string& name); 
private: 
    Path _path; 
    std::string _name; 
}; 

상기 Bean 클래스 데이터 표현이며, 그들은 서로 다른 두 층으로 사용된다. 한 레이어는 Bean 인터페이스를 사용하여 데이터의 getter에 액세스합니다. ResourceBean은 데이터 액세스 개체 (DAO) 클래스에서 액세스하며 데이터베이스 (예 :)에서 데이터를 가져 와서 ResourceBean을 채 웁니다.

class Service { 
protected: 
    /* 
    * Service object must not be instantiated (derived classes must be instantiated instead). Service is an interface for the generic Service. 
    */ 
    Service(); 

public: 
    virtual std::vector<Bean*>& list(const Bean::Path& path) = 0; 
    virtual ~Service(); 
}; 

class DummyService: public Service { 
public: 
    DummyService(); 
    ~DummyService(); 

    virtual std::vector<ResourceBean*>& list(const ResourceBean::Path& path); 
}; 

나는 문제가 std::vector<ResourceBean*>에서 컴파일러는 Bean 실제로 기본 클래스는 것을 이해하지 않는다는 사실과 관련이 있다고 생각 다음 DAO의

한 책임은 특정 경로 주어진 자원을 나열하는 것입니다 ResourceBean

제안 사항? 비슷한 주제로 읽었지만 필자의 경우 일부 솔루션이 작동하지 않았습니다. 제가 뭔가를 놓쳤다는 것을 지적하십시오. 미리 감사드립니다.

+1

더 나아 가기 전에, 코드가 타입 안전하지 않다는 것을주의하라. 'std :: vector '은'std :: vector '이 모든 표준을 지원하지 않기 때문에'std :: vector '은 (std :: vector ')의 유효한 하위 유형 'std :: vector '이 수행하는 작업 (예를 들어'Stan :: vector '에'Bean *'을 넣을 수있는 반면'ResourceBean *'을'std :: vector '). – Mankarse

+0

답장을 보내 주셔서 감사합니다. "std :: vector 가 std :: vector 의 모든 작업을 지원하지 않는다는 이유를 이해하려고합니다." 또한, "모든 bean을 * std :: vector 에 넣을 수 있지만, ResourceBean을 std :: vector "에 넣을 수는 있지만, Bean * (파생 된 클래스에 * 포함)? –

+0

예. 예를 들어 ** ** FooBean *을'std :: vector '('FooBean'은'Bean'의 하위 클래스입니다)에 넣을 수 있습니다. ** 당신은 ** FooBean을 넣을 수 없습니다 ** *'를'std :: vector '에 추가합니다. 어떤 코드가'Service :: list'를 사용하고'FooBean * '이 들어갈 수있는'std :: vector'에 대한 참조를 기대한다면,'DummyService :: :'에 의해 반환 된'std :: vector ' 목록'충분하지 않습니다. – Mankarse

답변

6

std::vector<Bean*>std::vector<ResourceBean*>은 서로 변환 할 수없는 완전히 다른 두 가지 유형입니다. C++에서는 그렇게 할 수 없으며 기본 클래스에 대한 포인터 벡터를 사용해야합니다. 그 때문에, 그 기능을 가지고 virtual 당신이 생각하는대로하지 않습니다 - 다른 반환 형식은 다른 메서드 서명 그래서 메서드를 오버로드하는 대신, 당신은 새로운 가상 메서드를 소개합니다. 어쨌든 추상 클래스의 인스턴스를 만들 수 없으므로 추상 클래스 (Service)에 대해 보호 된 생성자를 만들 필요가 없습니다. 나는 이것을 다음과 같이 쓸 것이다 :

#include <string> 
#include <vector> 
#include <iostream> 

class Bean { 
    public: 
    typedef std::string Path; 

    Bean() {} 
    virtual ~Bean() {} 

    virtual void say() const 
    { 
     std::cout << "I am a bean!\n"; 
    } 
}; 

class ResourceBean : public Bean { 
    public: 
    ResourceBean() {} 
    virtual ~ResourceBean() {} 

    virtual void say() const 
    { 
     std::cout << "I am a resource bean!\n"; 
    } 
}; 

class Service { 
public: 
    Service() {} 
    virtual ~Service() {} 

    virtual std::vector<Bean*>& list(const Bean::Path &path) = 0; 
}; 

class DummyService: public Service { 
    public: 
    DummyService() 
    { 
     for (int i = 0; i < 5; ++i) 
      beans_.push_back(new ResourceBean()); 
    } 

    virtual ~DummyService() {} 

    virtual std::vector<Bean *>& list(const Bean::Path &path) 
    { 
     return beans_; 
    } 

    private: 
    std::vector<Bean*> beans_; 
}; 

int main() 
{ 
    DummyService s; 
    std::vector<Bean *>& l = s.list("some path"); 
    for (std::vector<Bean *>::iterator it = l.begin(), eit = l.end(); 
     it != eit; ++it) 
    { 
     Bean *bean = *it; 
     bean->say(); 
    } 
} 
+0

의미가 있지만 Bean 클래스에는 getter 만 포함되어 있으므로 데이터로 채울 수 없습니다. std :: vector & DummyService의 목록 메서드에서 반환하는 방법이 있습니까?하지만 그 메서드에서 Bean으로 변환하는 ResourceBean? –

+0

@ user1570742 :'ResourceBean'은'Resource'에서 상속 받았을 때 기본 클래스 인'Resource'로 암시 적으로 변환 가능합니다. 내 대답을 편집하고 그 대신 몇 가지 예를 추가했습니다. –

+1

시간을내어 설명해 주셔서 감사합니다. 이제 완벽하게 작동합니다. –