C ++如何从main调用派生的基类函数

时间:2017-09-26 20:27:21

标签: c++ inheritance polymorphism

我有三个类,每个类都从另一个继承:B继承的A由C继承。我在每个类中都有一个虚函数。我想创建一个包含C类对象的A类指针,并像这样调用B类函数:

class A
{
public:
    virtual void doStuff() = 0;
};

class B : public A
{
public:
    virtual void doStuff() override;
};

class C : public B
{
public:
    void doStuff() override;
};

void B::doStuff()
{
    std::cout << "Starting doStuff in B\n";
    doStuff();
    std::cout << "Ending doStuff in B\n";
}

void C::doStuff()
{
    std::cout << "doStuff in C\n";
}

int main()
{
    A *pointer = new C();
    pointer->B::doStuff(); // This doesn't work
}

如果我略微更改主要部分,我会得到正确的输出:

int main()
{
    B *pointer = new C(); // Changed A to B
    pointer->B::doStuff();
}

输出

Starting doStuff in B
doStuff in C
Ending doStuff in B

如何更改原始代码以使用A类指针,最好只使用一个函数名称?

3 个答案:

答案 0 :(得分:1)

问题在于,B::doStuff引用了doStuffB的实施,而不是A的成员。如果您确定指针实际指向B的实例或从B派生的内容,那么您可以编写以下内容:

int main()
{
    A *pointer = new C();
    reinterpret_cast<B*>(pointer)->B::doStuff(); // This should work
}

如果您无法确定实例类型,请使用dynamic_cast

答案 1 :(得分:1)

A类型的指针无法确定默认情况下B doStuff版本的int main() { A *pointer = new C(); if(B *b_ptr = dynamic_cast<B*>(pointer)) b_ptr->B::doStuff(); //Will only be executed if dynamic_cast was successful } 是否可访问;你需要先抛出指针。

class A
{
public:
    virtual void doStuff() = 0;
    virtual ~A() noexcept = default;
};

另外,如果您要使用这样的多态,请确保您也将虚拟析构函数设为虚拟,否则清理不会表现出来。

ForeignKey

答案 2 :(得分:0)

以下是一些示例代码,说明我为什么要这样做。此代码将输出类似于XML的语法。调用“中间”类的函数允许我用正确的“IdentifiedRegion”标记包围任何派生类。

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

class Region
{
public:
    virtual void doStuff(std::string tabs) = 0;
};

class IdentifiedRegion : public Region
{
public:
    virtual void doStuff(std::string tabs) override;
};

class CircularRegion : public Region
{
public:
    CircularRegion(int latitudeIn, int longitudeIn, int radiusIn) : latitude(latitudeIn), longitude(longitudeIn), radius(radiusIn) {}
    void doStuff(std::string tabs) override;
private:
    int latitude;
    int longitude;
    int radius;
};

class CountryRegion : public IdentifiedRegion
{
public:
    CountryRegion(int countryCodeIn) : countryCode(countryCodeIn) {}
    void doStuff(std::string tabs) override;
private:
    int countryCode;
};

class StateRegion : public IdentifiedRegion
{
public:
    void doStuff(std::string tabs) override;
    StateRegion(std::string abbreviationIn) : abbreviation(abbreviationIn) {}
private:
    std::string abbreviation;
};

void IdentifiedRegion::doStuff(std::string tabs)
{
    std::cout << tabs << "<IdentifiedRegion>\n";
    doStuff(tabs + "\t");
    std::cout << tabs << "</IndentifiedRegion>\n";
}

void CircularRegion::doStuff(std::string tabs)
{
    std::cout << tabs << "<CircularRegion>\n";
    std::cout << tabs << "\t" << "<latitude>" << latitude << "</latitude>\n";
    std::cout << tabs << "\t" << "<longitude>" << longitude << "</longitude>\n";
    std::cout << tabs << "\t" << "<radius>" << radius << "</radius>\n";
    std::cout << tabs << "</CircularRegion>\n";
}

void CountryRegion::doStuff(std::string tabs)
{
    std::cout << tabs << "<CountryRegion>\n";
    std::cout << tabs << "\t" << "CountryCode>" << std::to_string(countryCode) << "</CountryCode>\n";
    std::cout << tabs << "</CountryRegion>\n";
}

void StateRegion::doStuff(std::string tabs)
{
    std::cout << tabs << "<StateRegion>\n";
    std::cout << tabs << "\t" << "<Abbreviation>" << abbreviation << "</Abbreviation>\n";
    std::cout << tabs << "</StateRegion>\n";
}

int main()
{
    Region *country = new CountryRegion(12);
    Region *state = new StateRegion("WA");
    Region *radius = new CircularRegion(10, 20, 30);

    reinterpret_cast<IdentifiedRegion*>(country)->IdentifiedRegion::doStuff("");
    reinterpret_cast<IdentifiedRegion*>(state)->IdentifiedRegion::doStuff("");
    radius->doStuff("");
}