从基类中选择子类......可能吗?

时间:2010-11-21 22:29:42

标签: c++ class-design

我正在学习C ++而且我遇到了问题。我需要一种方法来在基类中使用特定的子类。它有意义还是我使用了错误的方法? SelectBrand应该选择子类,我该怎么办?

以下是我的简化课程:


-----
class Protocol {

public:

    Protocol() {};
    ~Protocol() {};
    int openPort();
    int readPort(char *buffer);

.....

private:

        Protocol (const Protocol&);
};

int Protocol::openPort() {......};

int Protocol::readPort() {.........};

/***********************************************************************************/

class Device{

public:

        Device(Protocol& port):_protocol(port){}
        ~Device();
        virtual int getEvent(char *buffer) { return -1; }
        int Device::selectBrand();

        ..............

protected:

        Protocol& _protocol;

private:

        int brand;
        Device(const Device&orig);
};

Device::~Device() {}

int Device::selectBrand() {

       ......

       switch (X)

            case 1:

                    "use subclass Brand_B"

            case 2:

                    "use subclass Brand_B"

        .......

}

/***********************************************************************************/

class Brand_A:public Device {

public:

        Brand_A(Protocol& port);
        ~Brand_A();
        int getEvent(void *rawData);  

private:

        Brand_A(const Brand_A&);
};

Brand_A::Brand_A(Protocol& port):Device(port) {}

Brand_A::~Brand_A() {}

int Brand_A::getEvent(void *rawData) {


            .... readPort(......);

}

/***********************************************************************************/

class Brand_B:public Device {

public:

        Brand_B(Protocol& port);
        ~Brand_B();
        int getEvent(void *rawData);  

private:

        Brand_B(const Brand_B&);

};

Brand_B::Brand_B(Protocol& port):Device(port) {}

Brand_B::~Brand_B() {}

int Brand_B::getEvent(void *rawData) {


            .... readPort(......);

}

/* main **********************************************************/

int main(int argc, char **argv) {

        Device *mydev;

        char *buffer;

    ..............

    mydev->selectBrand();

    ..........

    mydev->getEvent(buffer);

    ...........

}

5 个答案:

答案 0 :(得分:2)

这不是一个好主意。

通常答案是dynamic_cast,但是从基类调用后代的特定行为通常是一个糟糕的设计符号。

您可以尝试反转类层次结构并使用模板。

答案 1 :(得分:1)

我想我应该充实我上面的评论。首先,您可以查看维基百科页面,了解有关abstract factory pattern的更多信息。基本上,它允许您访问接口的不同实现,并在运行时确定使用的实现。但是,您仍然不知道您将获得哪个实现,因为在返回接口实现的工厂方法中已决定。因此,您只能使用界面中的成员而不是特定的实现。使用上述类的示例如下:

class Device
{
    virtual int getEvent(void *rawData) = 0;
}

class BrandA : public Device
{
    // define constructors/destructors etc.

    int getEvent(void *rawData)
    {
        // BrandA's implementation for getEvent
    }
}

class BrandB : public Device
{
    // define constructors/destructors etc.

    int getEvent(void *rawData)
    {
        // BrandB's implementation for getEvent
    }
}

class DeviceFactory
{
    static Device *CreateDevice(/*any parameters for determining the device?*/)
    {
        // You probably don't want to randomly determine which implementation you use...
        if ((rand() % 2) == 0)
        {
            return new BrandA();
        }
        else
        {
            return new BrandB();
        }
    }
}

int main()
{
    // CreateDevice will decide which type of device we use, however we can only
    // explicitly reference the members of the base class (Device).
    Device *myDevice = DeviceFactory::CreateDevice();

    myDevice->getEvent();

    return 0;
}

答案 2 :(得分:0)

当C ++为你做这件事时,你可能会尝试实现类似多态的东西。如果在基类中定义虚方法并在子类中覆盖它们,则在指针上调用这些方法或对基类型的引用应该导致子类的实现被调用。

例如:

class BaseClass
{
    virtual void DoSomething()
    {
        printf("base");
    }

};

class SubClass : public BaseClass
{
    void DoSomething()
    {
        printf("sub");
    }
};

int main()
{
    BaseClass *myBase = new SubClass();
    myBase->DoSomething(); // should print "sub" to stdout

    return 0;
}

您必须知道在创建它时要使用的派生类型(子类的类型),以便实例具有派生类型的附加功能。如果不这样做,你得到的就是基类的功能,除了基类之外,你不能把它当作任何东西(或者如果你的基类继承了某些东西,那么继承层次结构的其他任何东西)。

如果他们实际上没有做任何不同的事情,您甚至可能希望使用成员来区分不同的实例。从代码示例中很难准确地告诉您要做什么。也许一个更具体的例子说明你想要实现的目标,而不是你试图实现它的目的。

答案 3 :(得分:0)

请让我重新解决这个问题。我有1个baseClass和一些子类; Brand_A .... Brand_N

现在,在main()中,我事先并不知道我将使用哪个子类;这个选择需要baseClass中的一个函数,我称之为selectBrand。我需要的是一种根据内部条件选择和使用正确子类的机制。我想伪装成main()所选的子类。怎么弄这个?

答案 4 :(得分:0)

我实现并测试了这段代码;它工作正常。它是好的设计还是可以做得更好?

class BehaviorBase
{
public:
    virtual ~BehaviorBase() {}
    virtual void DoSomethingOn(Object* obj) {}
};

class Object
{
public:
    BehaviorBase* behavior;
    void DoSomething();
    void ChangeBehavior(int param);
    ~Object();
}

class BehaviorA: public BehaviorBase
{
   void DoSomethingOn(Object* obj)
   {
    printf("Behavior A\n");
   }
};

class BehaviorB: public BehaviorBase
{
   string other_data;
   void DoSomethingOn(Object* obj)
   {
    printf("Behavior B\n");
   }
};

void Object::DoSomething()
{
    behavior->DoSomethingOn(this);
}

Object::~Object()
{
    delete behavior;
}

void Object::ChangeBehavior(int param)
{
    delete behavior;
    switch(param)
    {
        case 1: behavior = new BehaviorA; break;
        case 2: behavior = new BehaviorB; break;
    }
}    

int main(int argc, char **argv) {
    int param=1;
    Object *obj;
    obj= new Object;

    obj->ChangeBehavior(param);
    obj->DoSomething();     
    delete obj;
    return(0);
}