首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如果基类指针不能访问派生类成员函数,那么多态性又有什么好处呢?

如果基类指针不能访问派生类成员函数,那么多态性又有什么好处呢?
EN

Stack Overflow用户
提问于 2019-10-04 05:33:14
回答 3查看 81关注 0票数 0

要实现多态,我们需要使用指向派生类实例的基类指针。多态性的一切都很好,除非每个派生类都有一个或几个自己的成员函数?如果基类指针不能访问这些派生类成员函数,那么多态性有什么方便的呢?

下面是一个例子。"shape“是一个基类。"square“和"circle”是两个派生类。

代码语言:javascript
运行
复制
class shape {
public:
    virtual void getArea()=0;
};

class square: public shape {
private:
    int edge;
public:
    square(){edge = 1;}
    virtual void getArea(){  //polymorphism
        cout << edge*edge << "\n";
    }
    void getNumberOfEdge(){  //a new member function
        cout << "4\n";
    }
};

class circle: public shape {
private:
    int radius;
public:
    circle(){radius = 1;}
    virtual void getArea(){  //polymorphism
        cout << 3*radius*radius << "\n";
    }
    void getCurvature(){     //a new member function
        cout << 1/radius << "\n";
    }
};


int main(){
    shape* arr[2] = {
        new square(),
        new circle()
    };
    arr[0]->getArea();
    arr[1]->getArea();
    arr[0]->getNumberOfEdge();  //compiler error
}

getArea()是实现多态性的一个很好的例子。然而,访问派生类成员函数会给我带来编译器错误,我完全理解其中的原因。

EN

回答 3

Stack Overflow用户

发布于 2019-10-04 05:49:01

基类中的功能应该在基类中。特定于特定派生类的功能应该包含在这些派生类中。virtual函数允许代码操作形状并执行对任何形状有效的操作,而不必了解如何在现在和将来可能存在的每种形状类型上执行这些函数。

但是从设计的角度来看,我们不想仅仅为了每个派生类而向基类添加一堆虚函数,对吧?

如果这些操作在基类上是有意义的,那么它们可能应该放在基类上。如果它们是特定于形状的,则它们属于该功能有意义的特定类。

假设您有一个使用形状的系统,但没有八角形的派生类。多态性的要点是,今天可以编写代码,如果有人添加了八角形,这些代码将在以后的八角形上完美工作。

票数 3
EN

Stack Overflow用户

发布于 2019-10-04 05:51:55

有了适当的类型,你就可以很好地处理边缘问题的数量,把多态性带到边缘!

让我们添加一个类:

代码语言:javascript
运行
复制
// a base interface for all Edged shapes
struct HasEdges {
   virtual void getNumberOfEdges() const = 0;
    // side note: I'd prefer this getter to return an int
    // but keeping it as in the example
};

现在是Square (但不是Circle!)我们可以这样做:

代码语言:javascript
运行
复制
class Square: public Shape, public HasEdges {
// ...
public:
    void getNumberOfEdges() const override { /* implement */ }
// ...
};

main是这样的:

代码语言:javascript
运行
复制
int main(){
    shape* arr[2] = {
        new square(),
        new circle()
    };
    arr[0]->getArea();
    arr[1]->getArea();
    // some edgy thing below
    HasEdges* hasEdges = dynamic_cast<HasEdges*>(arr[0]);
    // above returns null on failure
    if(hasEdges) hasEdges->getNumberOfEdges();

    // releasing memory...
}
票数 0
EN

Stack Overflow用户

发布于 2019-10-04 05:54:20

运行时多态意味着运行时的多态行为。getArea()定义的行为在运行时根据它所指向的实例进行更改。所以,你把多态性和静态编译问题混在一起了。基类没有名为getNumberOfEdge()的成员函数,因此会出现编译器错误。

如果你想调用特定的实现,为什么不让编译器看到它并转换它呢?

代码语言:javascript
运行
复制
public:
    virtual void getArea()=0;
    template<typename T>
    const T * get() {
        return dynamic_cast<T *>(this);
    }
};

现在您可以将其强制转换为任何派生类型:

代码语言:javascript
运行
复制
auto square_instance = arr[0]->get<square>();
if (square_instance) {
    square_instance->getNumberOfEdge();
}

A different approach to run time polymorphism is suggested by Sean Parent.我喜欢它,并且现在更多地尝试这种方法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58227169

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档