如何从指向基类类型的指针调用派生类函数(C++)

Posted

技术标签:

【中文标题】如何从指向基类类型的指针调用派生类函数(C++)【英文标题】:How to call derived class function from pointer to base class type (C++) 【发布时间】:2018-01-11 04:34:52 【问题描述】:

上下文:我正在为嵌入式应用程序开发通信协议。 该协议基本上需要成为一个包装器,使其能够移植到不同的通信方法(串行、WiFi、蓝牙等),并能够支持与不同外围设备(DAC、加速度计等)的通信和控制。

这个想法是每个通信方法(在我的示例中为A_base)将有自己的实现,同时具有相同的外部功能,这样如果(例如)我们移动了外围设备的代码就不需要重写从字节到串行到 json-over-wifi。 每个外设实现基类的派生(在我的示例中为B_base)来处理特定于该外设的数据的传输,因此每个B 必须能够从A_base 的派生中调用函数,而不必知道哪个派生已使用。

当我编译以与以下相同的方式编写的代码时,会出现以下错误:

derivedB.cpp: In member function 'virtual void derivedB::setupData()':derivedB.cpp:xx: error: no matching function for call to 'A_base::callFromB(const char*, int&)'然后baseClasses.h:xx:yy: note: candidate: virtual void A_base::callFromB()virtual void callFromB() =0;candidate expects 0 arguments, 2 provided

我是否实现了我描述错误的功能,或者根本不可能,它是否需要特定版本的 C++? 我不是一个有经验的 C++ 程序员,所以任何帮助将不胜感激。

示例代码: 基类

/* ==== baseClasses.h ==== */
#ifndef BASECLASSES_H
#define BASECLASSES_H
#include <list>

// forward declarations
class A_base;
class B_base;

class A_base 
protected:
    std::list<B_base*> listOfBs;

public:
    A_base();
    void addB(B_base*);
    virtual void callFromB() =0;
    virtual void alsoCallFromB(short*, int) =0;
    virtual void alsoCallFromB(int*, int) =0;
    virtual void alsoCallFromB(float*, int) =0; // overloaded
;

class B_base 
protected:
    int someCommonInt;
    A_base* A;

public:
    B_base(int, A_base&);
    virtual void setupData() =0;
;

#endif

/* ==== baseClasses.cpp ==== */
#include "baseClasses.h"

A_base::A_base() 
void A_base::addB(B_base* b  listOfBs.push_back(b); 

B_base::B_base(int i, A_base& ref_A) 
    someCommonInt = i;
    A = &ref_A;
    A->addB(this);

A 的导数

/* ==== A_derived.h ==== */
#include "baseClasses.h"

class derivedA : public A_base 
public:
    virtual void callFromB(const char*, int);
    virtual void alsoCallFromB(short*, int);
    virtual void alsoCallFromB(int*, int);
    virtual void alsoCallFromB(float*, int); // overloaded
;

/* ==== A_derived.cpp ==== */
#include "A_derived.h"

void derivedA::callFromB(const char* msg, int foo) 
    // do something with msg and foo


void derivedA::alsoCallFromB(short* data, int len=1)  // overloaded derived function with default value
    // do something with short int data


void derivedA::alsoCallFromB(int* data, int len=1)  // overloaded derived function with default value
    // do something with int data


void derivedA::alsoCallFromB(float* data, int len=1)  // overloaded derived function with default value
    // do something with float data

B 的导数

/* ==== B_derived.h ==== */
#include "baseClasses.h"

class derivedB : public B_base 
private:
    int* intData;
    float* floatData;
    int arraySize;

public:
    virtual void setupData(int*, float*, int);
    void callAWithDataArrays();
    void callAWithSingleValue(int);
;

/* ==== B_derived.cpp ==== */
#include "B_derived.h"

void derivedB::setupData(int* iPtr, float* fPtr, int size) 
    intData = iPtr;
    floatData = fPtr;
    arraySize = size;
    A->callFromB("B setup done.\n", 0);


void derivedB::callAWithDataArrays() 
    A->alsoCallFromB(intData, arraySize);
    A->alsoCallFromB(floatData, arraySize);


void derivedB::callAWithSingleValue(int idx) 
    A->alsoCallFromB(intData[idx]);
    A->alsoCallFromB(floatData[idx]);

主程序

#include "A_derived.h"
#include "B_derived.h"

int main(int argc, char** argv) 
    int myInts[] = new int[8];
    float myFloats[] = new float[8];
    float anotherFloat = 1.23;

    A_derived myA;
    B_derived myB(1337, (A_base&)myA);
    myB.setupData(myInts, myFloats, 8);

    myB.callAWithDataArrays();
    myB.callAWithSingleValue(4);

    return 0;

【问题讨论】:

【参考方案1】:

你有一个纯虚函数virtual void callFromB() =0;,它没有在派生类中被覆盖,即:

virtual void callFromB(const char*, int); != virtual void callFromB() 

你可以改A_base::callFromB() to A_base::callFromB(const char*, int)

【讨论】:

以上是关于如何从指向基类类型的指针调用派生类函数(C++)的主要内容,如果未能解决你的问题,请参考以下文章

关于C++基类、派生类的引用和指针

在 C++ 中将指向基类的指针传递给派生类的成员函数

virtual虚函数

派生类指针如何调用基类函数

如何从包含基类指针的容器中调用派生类函数(基于其类型)?

c++ 虚函数 如何调父类 而非子类