我们知道,派生类成员函数可以通过C ++中的基类指针访问,提供这些成员函数必须是虚拟的。有没有办法从基类指针访问派生类成员函数非虚拟或纯虚拟。
即。我想调用派生类成员函数,它们只出现在派生类和放大器中。通过基类指针不在基类中。我怎么做到这一点?
例如,如果我设计工厂设计模式,
from vlc import Instance
playlist = ['/home/user/Music/01 Signs.mp3','/home/user/Music/2U.mp3']
player = Instance()
mediaListPlayer = player.media_list_player_new()
mediaList = player.media_list_new()
for element in playlist:
mediaList.add_media(player.media_new(element))
mediaListPlayer.set_media_list(mediaList)
mediaListPlayer.play()
mediaListPlayer.audio_set_volume(80)
答案 0 :(得分:1)
我想调用仅在派生类&中出现的派生类成员函数。通过基类指针不在基类中。我怎么做到这一点?
您不能使用指向基类的指针调用派生类的非虚成员函数。
您需要一个指向派生类的指针。最简单的方法是使用dynamic_cast
获取指向派生类的指针,检查转换是否成功,然后使用派生类指针调用派生类成员函数。
更好的方法是在基类中提供虚拟成员函数并在派生类中实现它。
答案 1 :(得分:1)
您可以使用dynamic_cast
执行所需操作,但这会导致代码审核结果令人失望。相反,我推测你使用与printVehicle
class Vehicle
{
public:
// without a virtual destructor you are walking into
// a very bad bug. The wrong destructor may be called.
virtual ~Vehicle()
{
}
virtual void printVehicle() = 0;
// Specific stuff that all children must provide
virtual void doTypeSpecificStuff() = 0;
// this is actually a bit of a ideological weird. I'm not sure I can call
// it a flaw. By making this factory function a member of Vehicle, Vehicle
// must now know its children. If this is the case, the VehicleType enum
// should probably be a member of Vehicle, but personally I think this
// factory should be a totally free function.
static Vehicle* Create(VehicleType type);
};
class TwoWheeler: public Vehicle
{
public:
void printVehicle()
{
cout << "I am two wheeler" << endl;
}
void doTypeSpecificStuff()
{
cout << "Doing two wheeler stuff" << endl;
}
};
省去其他两个班级Vehicle::Create
以节省空间。
int main()
{
Vehicle* basePtr = Vehicle::Create(VT_TwoWheeler);
basePtr->doTypeSpecificStuff(); //HOW TO ACHIEVE THIS CALL
// leaking memory here, so
delete basePtr;
// but also look into std::unique_ptr. Much better suited to this behaviour
}
事实上,让我们立即就std::unique_ptr
的最终评论采取行动。 unique_ptr
为您管理动态分配,因此您不必使用delete
来混淆代码,并且可能会错过一个或delete
过早的风险。只要unique_ptr
在范围内,unique_ptr
指针就有效。如果你可以编译,指针是好的,除非你做了一些愚蠢的事情,就像从来没有指向任何东西或手动删除指针。
虽然我们正在努力,但我们已经消除了我之前关于vehicle::Create
的担忧。
首先,我们定义一个自由函数来替换Create
并返回unique_ptr
。由于我不想在我的代码中进行if (ptr != NULL)
检查以确保确实创建了一个对象,所以当我们无法匹配所提供的车辆类型时,我们也会对它产生很大的影响。通过抛出异常与类。
而不是if
- else if
链,我们会使用更优雅的switch
语句。
std::unique_ptr<Vehicle> SmarterVehicleFactory(VehicleType type)
{
switch (type)
{
case VT_TwoWheeler:
return std::make_unique<TwoWheeler>();
case VT_ThreeWheeler:
return std::make_unique<ThreeWheeler>();
case VT_FourWheeler:
return std::make_unique<FourWheeler>();
default:
throw std::runtime_error("Invalid Vehicle type");
}
}
然后我们将使用这个新功能
int main()
{
try
{
std::unique_ptr<Vehicle> basePtr = SmarterVehicleFactory(VT_TwoWheeler);
basePtr->doTypeSpecificStuff();
basePtr = SmarterVehicleFactory(VT_ThreeWheeler);
// unique_ptr freed the TwoWheeler for us.
basePtr->doTypeSpecificStuff();
basePtr = SmarterVehicleFactory(VT_FourWheeler);
basePtr->doTypeSpecificStuff();
// just for laughs we will ask for a FiveWheeler, which we have not yet
// fully implemented
basePtr = SmarterVehicleFactory(VT_FiveWheeler); // will throw exception
basePtr->doTypeSpecificStuff(); // will not be executed
}
catch (const std::exception & exc)
{
cerr << "Rats! Something bad happened: " << exc.what();
// basePtr will be unmodified and still pointing to a FourWheeler
}
} // basePtr will go out of scope here and clean up our memory for us.
这种方法的美妙之处在于,没有一个班级知道任何其他课程。您可以将Vehicle
放入带有SmarterVehicleFactory
原型和车辆类型列表的标题中,并隐藏其他所有内容。用户什么也看不见。每个人都被置于黑暗中。
为什么那么好?因为现在您可以更改除Vehicle
接口类之外的任何上述类,而不会对任何其他类产生任何影响。这使您的代码更易于维护和调试。
答案 2 :(得分:0)
我试图找到不使用继承而使用多态的最佳方法,因为我想避免虚拟调用。我正在寻找一种方法来改进我目前拥有的东西(无济于事),我偶然发现了这个问题。这是我目前能做的最好的:
template<class VehicleDetails>
class Vehicle {
VehicleDetails details;
public:
VehicleDetails& getDetails() {
return details;
}
const VehicleDetails& getDetails() const {
return details;
}
void printDetails() const {
details.printDetails();
}
}
class TwoWheeler {
public:
void printDetails() const {
cout << "I am two wheeler" << endl;
}
void specificTwoWheelerMethod() const {
cout << "I am specific functionality" << endl;
}
}
然后你就这样使用它:
Vehicle<TwoWheeler> vehicle;
vehicle.printDetails(); // prints "I am two wheeler"
不幸的是,这使事情变得复杂。现在,除非您知道车辆的类型,否则每个接受车辆的类/结构或函数都必须进行模板化。
template<class VehicleDetails>
void doGeneralVehicleThings(const Vehicle<VehicleDetails>& vehicle) {
// ...
}
从好的方面来说,当您知道类型时,您可以通过 getDetails() 方法访问特定功能,而无需涉及任何转换或运行时开销:
void doTwoWheelerThings(const Vehicle<TwoWheeler>& twoWheelerVehicle) {
twoWheelerVehicle.getDetails().specificTwoWheelerMethod(); // prints "I am specific functionality"
}