我有三个类,每个类都从另一个继承: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类指针,最好只使用一个函数名称?
答案 0 :(得分:1)
问题在于,B::doStuff
引用了doStuff
类B
的实施,而不是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("");
}