2015-01-08 4 views
1

if 또는 switch 문을 사용하지 않고 변수 값에 따라 함수를 실행하려면 어떻게해야합니까? 순간 변수의 값에 따라 어떻게 다른 기능을 실행할 수 있습니까?

나는 많은 코드를 반복하고 2 개 개의 변수를 내가 소켓에서 읽기하고 데이터를 표현이

같은 것을하고 있어요. 는 내가 아무 정말 깨끗한 솔루션입니다,하지만 당신이 정말로 "클래스 % d 개"라는 클래스가있는 경우, 당신은 당신의 코드를 약간 만들기 위해 전처리를 이용할 수

//Class1.h 
class Class1 { 
public: 
    Class1(); 
    virtual ~Class1(); 

    unsigned char mode = 0x00; 
    unsigned char type = 0x00; 

    Interface* o;//in this case I’m creating an object not running a function 
}; 

//Class1.cpp 

#include "Class1.h" 

Class1::Class1(){ 

    switch(mode){ 
    case 0x00: 
     switch(type){ 
     case 0x00: 
      o = new Class2(); 
      break; 
     case 0x01: 
      o = new Class3(); 
      break; 
     case 0x02: 
      o = new Class4(); 
      break; 
     } 
     //case 0x03 
     //case 0x04 
     //... 
     break; 
    //case 0x01 
    //case 0x02 
    //... 
    default: 
     break; 
    } 

} 
+0

A) 숫자와 클래스 사이의 연결이 있습니까? 어떤 임의의 순서라면, 컴퓨터는 어떻게 든 알아야합니다. b) 왜 각 클래스에 대해 if를 만드는 것은 너무 많은데, 클래스가 너무 많지는 않은가? 수많은 수업이 있기 때문에 디자인을 너무 많이 사용해야합니다. – deviantfan

+0

소켓에서 데이터를 읽는 중입니다. 2 개의 변수가 데이터를 읽는 중이므로, 데이터에 따라 다른 작업을 수행해야합니다. – TheGamingNexus

+1

인스턴스에 일종의 맵을 사용할 수 있습니다. –

답변

0

내가, 자체 공장 클래스로 이런 일을 인스턴스 작성을 분할 것 :

#include <map> 
#include <cstdint> 
#include <iostream> 

class Interface 
{ 
public: 
    virtual ~Interface() = 0; 
}; 
Interface::~Interface() {} 

class InterfaceFactory 
{ 
public: 
    typedef Interface* (*InterfaceCreator)(); 
    void registerInterface(unsigned char mode , unsigned char type, InterfaceCreator creator) 
    { 
     int16_t key = getKey(mode, type); 
     table[key] = creator; 
    } 
    Interface* createInterface(unsigned char mode, unsigned char type) const 
    { 
     int16_t key = getKey(mode, type); 
     Interface* iface = nullptr; 
     std::map<int16_t, InterfaceCreator>::const_iterator cit = table.find(key); 
     if (cit != table.end()) 
      iface = (*(cit->second))(); 
     return iface; 
    } 
private: 
    int16_t getKey(unsigned char mode, unsigned char type) const 
    { 
     int16_t key = mode; 
     key <<= 8; 
     key += type; 
     return key; 
    } 
    std::map<int16_t, InterfaceCreator> table; 
}; 

//StreamProcessor.h 
class StreamProcessor { 
public: 
    StreamProcessor(const InterfaceFactory& fact) 
     : factory(fact) 
    {} 
    virtual ~StreamProcessor(); 
    bool initHandler(unsigned char mode = 0x00, unsigned char type = 0x00); 
private: 
    const InterfaceFactory& factory; 
    Interface* o;//in this case I’m creating an object not running a function 
}; 

//StreamProcessor.cpp 

//#include "StreamProcessor.h" 

bool StreamProcessor::initHandler(unsigned char mode , unsigned char type) 
{ 
    o = factory.createInterface(mode, type); 
    return o != 0; 

} 

class Class2 : public Interface 
{ 
public: 
    static Interface* create() 
    { 
     return new Class2; 
    } 
}; 
class Class3 : public Interface 
{ 
public: 
    static Interface* create() 
    { 
     return new Class3; 
    } 
}; 

int main() 
{ 
    InterfaceFactory factory; 
    factory.registerInterface(0x00, 0x00, &Class2::create); 
    factory.registerInterface(0x00, 0x01, &Class3::create); 
    StreamProcessor sp(factory); 
    if (!sp.initHandler(0x00, 0x01)) 
    { 
     throw "Unknown interface type"; 
    } 
    return 0; 
} 
+0

위대한 작품 : D 조 감사합니다! – TheGamingNexus

0

를받을 데이터에 따라 다른 무언가를 할 필요가 변수의 값을 클래스 이름의 일부로 사용하면 더 짧아집니다.

나는 이것을 너무 좋아하지 않지만 너무 많은 대안을 생각할 수 없다.

#define HANDLE_HUNDREDS_OF_CASES(x) case x: o = new Class##x(); break; 

int type=1; 
switch(type) { 
HANDLE_HUNDREDS_OF_CASES(0); //< Will construct a new Class0 if type==0 
HANDLE_HUNDREDS_OF_CASES(1); //< Will construct a new Class1 if type==1 
HANDLE_HUNDREDS_OF_CASES(2); // Etc ... 
HANDLE_HUNDREDS_OF_CASES(5); 
HANDLE_HUNDREDS_OF_CASES(100); 

default: 
    break; 
} 

그냥 기능이 아닌 생성자를 호출 할 경우, 당신은 함수 포인터의 배열을 만들 수 있으며, 해당 배열의 인덱스로 변수를 사용합니다.

0

벡터를 사용하여 모든 클래스 개체를 저장하고 수신 한 데이터로 개체를 가져 오는 이유는 무엇입니까?

class Base{ 
     virtual void doSomeThing(); 
    } 
    class A : public Base{ 
     virtual void doSomeThing() { 
     } 
    } 

    class B : public Base{ 
     virtual void doSomeThing() { 
     } 
    } 

    class Handler { 
     vector<Base *> vet; 
     void init() { 
      vet.push_back(new A()); 
      vet.push_back(new B()); 
     } 

     void handle(int code) { 
      Base * obj = vet.get(code); 
      obj->doSomeThing(); 
     } 
    } 
+0

수십 또는 수백 개의 가능한 클래스가 있다고 가정하면 많은 메모리가 낭비됩니다. 단 2-3 개의 클래스가 있다면 스위치를 사용하거나 관계없이 사용하십시오. – tux3

+0

몇백 개의 포인터가 큰 문제는 아닙니다. 또한, 당신이 마술처럼 스위치 성명을 사용하여 메모리를 절약하는 것처럼, 당신은 단지 메모리 구조를 실행 가능한 코드로 옮깁니다. 객체 자체를 할당하는 경우 옵티마이 저는 할 수 있으면 변경을 가할 것입니다. 특히 객체가 가상 테이블을 제외한 다른 멤버를 가지지 않는 경우 (좋은 옵티마이 저는 아마도 이것을 함수 포인터의 벡터로 바꿀 것입니다). – Wug

관련 문제