【问题标题】:Trying to point a base class function pointer to a derived class function试图将基类函数指针指向派生类函数
【发布时间】:2020-10-02 23:21:37
【问题描述】:

我正在尝试实施一种策略模式。现在我正在制作一个函数指针向量,它接受一个整数向量作为它们的类型。我把这个函数指针向量称为“算法”。我希望向量中的每个函数指针都指向不同的排序类(合并、冒泡或插入)。我的类结构是这样的:Algorithm是基类,Sort是继承自Algorithm的抽象类,然后Merger、Insertion、Bubble都继承自Sort。我现在遇到的问题是我似乎无法让我的 mergePointer 指向 Merger 类中的sortFunc()。当我尝试执行我的代码时,它说:

main.cpp:59:28:错误:使用未声明的标识符“sortFunc” 合并指针 = sortFunc(); ^

我最初认为问题出在范围分辨率上,所以我在sortFunc() 前面添加了Merger::,我得到了同样的错误。我不熟悉多态性,甚至不确定我想要做的事情是否可行,有什么想法吗?

class Algorithm{

private:
public:

    vector<int> data;

    static std::vector<void (*)(std::vector<int>&)> algo;

    void (*activeAlgo)(std::vector<int>&);

    enum SortingAlgorithms{
        Merge = 0, Insertion, Bubble, Last
    };

    void load(){
        void (*mergePointer)(vector<int>&);
        mergePointer = sortFunc();
        algo.push_back(mergePointer);
    }
    
    void select(SortingAlgorithms sort){
        
    }
    
};

//abstracted class
class Sort: public Algorithm{
private:
public:
    virtual void sortFunc() = 0; //pure virtual function  
};

class Merger: public Sort{
private:
public:
    void sortFunc(){
        data = mergeSort(data);
        print(data);
    }
};

class Insertion: public Sort{
private:
public:
    void sortFunc(){
        printVec(data);
        insertionSort(data);
        printVec(data);
    }
};

class Bubble: public Sort{
private:
public:
    void sortFunc(){
        printVector(data);
        bubbleSort(data);
        printVector(data);
    }
};

int main(){
    Sort *myAlgo;
    myAlgo->select(Algorithm::Bubble);
}

【问题讨论】:

  • @CrashMan123 很明显,类算法中使用的名称 sortFunc 尚未声明。
  • Algorithm 应该是一个模板化的类或函数,可以用具体的Sort 实现来实例化。甚至都不需要抽象基类 看std::sort() 例如,算法只需要一个容器(迭代器)接口,
  • @VladfromMoscow 我在 Merger、Bubble 和 Insertion 类中声明了 sortFunc。我如何去调用那些在类算法?
  • @CrashMan123 任何使用的名称都应在使用前声明。
  • @CrashMan123 基类对其派生类一无所知。

标签: c++


【解决方案1】:

请注意,void(*)(std::vector&lt;int&gt;&amp;) 只能指向命名空间函数或静态成员。指向成员的指针是特定于类的,必须使用特殊运算符 .* 或 -&gt;* 调用。您可以实现的是具有虚拟基类的 CRTP(为简洁起见,去掉了静态向量和其他花里胡哨):

#include <iostream>
#include <cstdlib>

    class ActorBase
    {
    public:
       // virtual interfaces
       virtual void action() = 0;
    };

    template <class  T>
    class Actor : public ActorBase
    {
    protected:
        typedef void(T::* FuncPtr)(/* params */);
        FuncPtr algo;
    public:
        void action() 
        { 
            /* do call algo for appropriate object by treating this as pointer to T */
            (dynamic_cast<T*>(this)->*algo)(/* args */);
        }
    };

    class Concrete : public Actor<Concrete>
    {
       void bar() {  std::cout << "Hello, Concrete!" << std::endl; }
    public:
       Concrete() { algo = &Concrete::bar; }
    };

int main()
{
    Concrete a;
    a.action();
    return EXIT_SUCCESS;
}

Curiously Recurrent Template Actor 是一个非常特殊的模板,它可以将指向自身的指针转换为派生类。尽管如此,它对Concrete 一无所知,例如typedef 或成员。如果它需要传递一些这样的特征,Actor 应该派生自一个专门用于具体 T 的模板类,称为 trait 类。

虽然不确定这种变态的方法是解决您的 X 问题实际需要的方法,但至少它在语法上是正确的。 Here 是一个规范的 CRTP。

注意,成员指针的调用需要.* \ -&gt; AND 括号,因为调用运算符() 的优先级高于.*。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-26
    • 1970-01-01
    • 2023-04-07
    • 2017-07-18
    • 2023-03-22
    相关资源
    最近更新 更多