2013-02-24 2 views
0

두 종류의 클래스를 만들고 싶습니다. 클래스는 비슷한 "set"함수를 갖지만 설정 funct는 클래스 B에서 "int"를 가져오고 클래스 C에서 double을 얻습니다 (A는 추상 calss이지만 필요하지 않습니다). 무엇을해야합니까?C++ 및 가상 기능 클래스

class A{ 
    int x; 
public: 
    A (int t=1): x(t){} 
    virtual void set()=0; 
} 

class B: public A{ 
    int y; 
public: 
    virtual void set (int y); 
}; 

class C: public A{ 
    double y; 
public: 
    virtual void set (double y); 
}; 

void main() 
{ 
    B b; //error 
    C c; //error 
} 
+3

상속없이 두 개의 별도 클래스를 만드시겠습니까? – juanchopanza

+0

은 상속됩니다. 두 개의 칼시는 B와 C이다. – YkI

+2

상속보다이 템플릿을 사용하는 것이 더 적합 할 것입니다. – Chad

답변

2

는 하나의 템플릿 클래스를 작성하고 당신이 시간에해야하는 지금의 인스턴스, 또는 템플릿 클래스의 형식 정의 B와 C 가상 함수는 동일한 시그너처를 가져야합니다 (예외가있을 수 있지만 이는 해당 케이스와 관련이 없습니다). 그래서 해결책은 모든 경우를 해결할 논증입니다. 단지 특정 하나의 함수에

패스의 모든 변종 및 사용 :이 변종은

class A { 
public: 
    virtual void set(int, double) = 0; 
}; 
class B { 
    int y; 
public: 
    virtual void set(int val, double) { y = val; } 
}; 
class C { 
    double y; 
public: 
    virtual void set(int , double val) { y = val; } 
}; 

이 아주 좋은 해결책이 아니다 및 확장 성이 좋지 않기 때문에 우리가 노동 조합 사용할 수 있습니다

Union Arg { 
    int i; 
    double d; 
}; 

class A { 
public: 
    virtual void set(Arg a) = 0; 
}; 
// derived classes are trivial, so omitted 

연합 (EU)은 안전 입력하지, 그래서 우리는 매개 변수에 다른 계층 구조를 가지고 부스트 :: 대신

변형 다른 방법을 사용할 수 있습니다

struct Arg { 
    virtual ~Arg(); 
}; 
struct IntArg : Arg { 
    int m_value; 
}; 
struct DoubleArg : Arg { 
    double m_value; 
}; 
class A { 
    virtual void set(const Arg &a) = 0; 
}; 
class B { 
    int y; 
public: 
    virtual void set(const Arg &a) { y = dynamic_cast<const IntArg &>(a).m_value; } 
}; 
class C { 
    double y; 
public: 
    virtual void set(const Arg &a) { y = dynamic_cast<const DoubleArg &>(a).m_value; } 
}; 

static_cast를 사용할 수 있으며 Arg에서 가상 소멸자가 필요하지 않지만 덜 안전합니다.

이들은 매우 다양 할 수 있습니다. 어떤 프로그램이 가장 적합한 프로그램인지는 프로그램 요구 사항에 따라 결정할 수 있습니다.

+0

좋은 생각! 감사합니다 !!! – YkI

+0

이것은 나쁜 생각은 아니지만 여러분이 물어 본 것과는 완전히 다른 문제를 해결합니다. 그래서 당신은 그 차이를 이해하지 못하거나 당신이 물었던 것을 이해하지 못했습니다. – Slava

+0

@Slava 글쎄, 나는 A의 원래 내용을 놓쳤다는 것을 인정하지만 쉽게 템플릿에 다시 추가 할 수있다. 질문하는 모든 질문은 유사하게 보이지만 다른 데이터 유형 (도메인 템플릿이 생성 된 정확한 문제)에 따라 작동하는 두 개의 클래스를 갖는 방법이었습니다. –

0

트릭은 B와 C의 공통 부분을 찾아서 기본 클래스에 배치하는 것입니다. 다른 물건이 파생 클래스의 매개 변수를 생성자로 이동해야합니다

void B::set(std::string s) { 
    stringstream ss(s); 
    ss >> a; 
} 
void C::set(std::string s) { 
    stringstream ss(s); 
    ss >> b; 
} 

기능은 동일 보이지만, 실제로 :

class A { 
    virtual std::string get() const=0; 
    virtual void set(std::string s)=0; 
}; 
class B : public A { B(int a) : a(a) { } int a; }; 
class C : public A { C(float b) : b(b) { } float b; } 

이 기능을 구현하는 방법을, 다음이 필요합니다 다른 연산자 >> 호출. ,

template< typename T > class A 
{ 
public:    A() : mValue() {} 

      void Set(T value) { mValue = value; } 

private: T  mValue; 
}; 

typedef A<int> B; 
typedef A<double> C; 
+0

B와 C는 동일한 "int x"와 다른 변수 "float c"및 "int a"를가집니다. 또한 나는 B와 C가 같은 이름 함수 "set"을 공유하고 싶다. – YkI

+0

ykl : get/set() 함수를 구현하기 위해 std :: string에서 int/float 로의 변환이 필요하다. 번역. – tp1

+0

나는 이해하지 못했다고 생각합니다 ... – YkI

1

가 있지만, 우선,이 문제를 해결하기 위해 꽤 많은 변종이 있습니다

1

상속 및 가상 일을 도랑. 가상 함수를 통해 정적으로 알 수없는 유형의 결과에 쉽게 액세스 할 수 없습니다. 그래서 :

class A 
{ 
private: 
    int x_; 
public: 
    A(int const t = 1): x_(t) {} 
}; 

class B 
    : public A 
{ 
private: 
    int y_; 
public: 
    void set(int const y); 
}; 

class C 
    : public A 
{ 
private: 
    double y_; 
public: 
    void set(double const y); 
}; 

int main() 
{ 
    B b; // OK 
    C c; // OK 
} 

참고 클래스 A의 끝에 세미콜론 대신 void mainint main.

이러한 세부 사항이 중요합니다.

그렇지 않으면 긴 야생 거위 추격전에서 당신을 도울 사람들을 보낼 수 있습니다. 그리고 너는 그걸 원하지 않지, 그렇지? 따라서 게시하려는 코드가 컴파일러에 의해 승인되었는지 확인하십시오. 단, 표시하려는 문제가있는 부분은 컴파일하지 않는 것이 좋습니다.