Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 纯虚函数问题_C++_Oop_Polymorphism_C++14_Virtual Functions - Fatal编程技术网

C++ 纯虚函数问题

C++ 纯虚函数问题,c++,oop,polymorphism,c++14,virtual-functions,C++,Oop,Polymorphism,C++14,Virtual Functions,我有一个基类,其中有一个纯虚函数,通过这个函数,我想在其他派生类中重写它(如果可能的话,在一些具有不同数量参数的派生类中) 所以在MergeSort子类中,我有一个MSort方法,它需要不同数量的参数,因为它是递归完成的 现在有了这个函数和这些参数,我得到了这个错误 “MergeSort:”无法实例化抽象类。但是如果我重写基类中的Sort方法,效果很好,但是我不需要一个参数 我还尝试用不同数量的参数声明另一个虚拟函数,并在MergeSort类中定义它,我得到了同样的结果 我还想澄清一下,我还有其

我有一个基类,其中有一个纯虚函数,通过这个函数,我想在其他派生类中重写它(如果可能的话,在一些具有不同数量参数的派生类中)

所以在MergeSort子类中,我有一个MSort方法,它需要不同数量的参数,因为它是递归完成的

现在有了这个函数和这些参数,我得到了这个错误 “MergeSort:”无法实例化抽象类。但是如果我重写基类中的Sort方法,效果很好,但是我不需要一个参数

我还尝试用不同数量的参数声明另一个虚拟函数,并在MergeSort类中定义它,我得到了同样的结果

我还想澄清一下,我还有其他用于不同算法(冒泡排序、插入排序等)的子类,它们的实现类似于MergeSort(构造函数和排序函数),但排序函数没有与上面的基类相同的参数(仅用于图形界面)

那么,是否可能有一个具有不同数量参数的重写方法?或者我上面所说的任何其他解决方案

// BASE CLASS
// Forward declaration
class Interface;

/**
 * Base class from which the sorting algorithms classes will inherit (Polymorphic class) 
 * The base class will allow us to create a sequence with n elements    
 */
class SortingAlgorithms
{

protected:
    std::vector<sf::RectangleShape> sequence;       // vector which will contain a randomized sequence
    std::vector<sf::RectangleShape> sequenceCpy;    // a copy of sequence used for interaction features
    sf::RenderWindow& window;                       // initializes the window
    int minimum, maximum;                           // the range in which the elements will be randomized
    int elements;                                   // the number of elements which will be initialized

public:
    SortingAlgorithms();

    /** SortingAlgorithms() - class constructor which initializes the sequence
     *  @param min - the minimum value for randomizing
     *  @param max - the maximum value for randomizing
     *  @param els - the number of elements to generate
     *  @param win - since the window will be initialized only once (singleton pattern); 
     *               it will be needed to pass on this object to almost every function that has 
                     graphics features
     */
     SortingAlgorithms(int min, int max, int els, sf::RenderWindow& win);


     // A pure virtual function for overriding and param init which is what I described about win param from SortingAlgorithms constructor 
     virtual void Sort(std::unique_ptr<Interface>& init) = 0;
};



class MergeSort : public SortingAlgorithms
{
public:
    MergeSort(int min, int max, int els, sf::RenderWindow& win);
    
    void Merge(std::unique_ptr<Interface>& init, int first, int mid, int last);
    void MSort(std::unique_ptr<Interface>& init, int first, int last);
};
//基类
//远期申报
类接口;
/**
*排序算法类将从中继承的基类(多态类)
*基类将允许我们创建一个包含n个元素的序列
*/
类排序算法
{
受保护的:
std::vector sequence;//将包含随机序列的向量
std::vector sequenceCpy;//用于交互功能的序列副本
sf::RenderWindow&window;//初始化窗口
int minimum,max;//元素随机化的范围
int elements;//将被初始化的元素数
公众:
排序算法();
/**SortingAlgorithms()-初始化序列的类构造函数
*@param min-随机化的最小值
*@param max-随机化的最大值
*@param els-要生成的元素数
*@param win-因为窗口将只初始化一次(单例模式);
*需要将此对象传递给几乎所有具有
图形特征
*/
排序算法(int-min、int-max、int-els、sf::RenderWindow&win);
//一个用于重写和param init的纯虚拟函数,这是我在SortingAlgorithms构造函数中描述的关于win param的内容
虚空排序(std::unique_ptr&init)=0;
};
类MergeSort:公共排序算法
{
公众:
合并排序(int-min、int-max、int-els、sf::RenderWindow&win);
无效合并(std::unique_ptr&init,int first,int mid,int last);
void MSort(std::unique_ptr&init,int first,int last);
};

如注释中所述,您必须对所有覆盖使用相同的签名。为此,您可以使用以下方法: 使用重写函数作为一种入口点,在其中调用执行排序的实函数(可能是私有函数)。举例说明该方法:

类排序算法
{
公众:
虚空排序(int-arr[],int-n)=0;
};
类BubbleSort:公共排序算法
{
公众:
无效排序(整数arr[],整数n){
此->气泡_排序(arr,n);
}
私人:
无效气泡_排序(int arr[],int n){
//实施
}
};
类合并排序:公共排序算法
{
公众:
无效排序(整数arr[],整数n){
这->合并排序(arr,0,n-1);
}
私人:
无效合并排序(整数arr[],整数l,整数r){
//递归实现
}
无效合并(整数arr[],整数l,整数m,整数r){
//实施
}
};

下面是另一种解决重载具有不同数量参数的虚拟方法问题的方法。如果
参数类型
为同一类型,则这将起作用。如果类型不同,则可能必须应用
模板
并使用
模板类型推断
或使用
可变函数模板

下面是示例代码和使用GCC 10.2编译的生成的程序集,可以在上看到

CPP

ASM

正如我已经说过的,当函数声明定义中每个参数放置的类型都是相同的类型时,这将在简单的情况下起作用。这里的诀窍是获取具有最多参数的函数版本,并在抽象基类中的纯虚函数声明中使用该版本

现在,如果类型不同,您仍然可以执行此操作,但它们的位置必须匹配,例如:

class Base {
public:
    virtual void foo(int a, double b, char c) = 0;
};

class Bar : public Base {
public:
    virtual void foo(int a, double b, char c) override { } // uses all three
};

class Baz : public Base {
public:
    virtual void foo(int a, double b, char c = '') override {} // uses only the int and double
};

class Biz : public Base {
public:
    virtual void foo(int a, double = 0.0, char c = '') override{} // uses only the int
};

这应该也可以,但我还没有测试过。

您必须在所有重写上使用相同的签名。如果派生类需要的参数与抽象类所期望的不同,则这是一种糟糕的代码味道。这表明派生类不能满足基类的要求,这意味着多态is-a关系有点粗略。或者基类太过约束,可能需要重新设计,以便更适合派生类用例。我认为您应该重写
Sort
函数,而不尝试更改签名,并将其用作一种入口点,在其中调用执行排序的实函数(可能是private),例如,以递归方式或其他方式,尽管您已经接受了答案,但我仍然发布了一个答案,为您提供了另一种方法或途径来解决具有不同参数计数的函数重载问题。鉴于OP的要求,建议对许多实现应用任意数量的没有任何用途的参数是一种巨大的设计气味。Th
Bar::foo(int, int, int, int):
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], rdi
        mov     DWORD PTR [rbp-12], esi
        mov     DWORD PTR [rbp-16], edx
        mov     DWORD PTR [rbp-20], ecx
        mov     DWORD PTR [rbp-24], r8d
        nop
        pop     rbp
        ret
Baz::foo(int, int, int, int):
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], rdi
        mov     DWORD PTR [rbp-12], esi
        mov     DWORD PTR [rbp-16], edx
        mov     DWORD PTR [rbp-20], ecx
        mov     DWORD PTR [rbp-24], r8d
        nop
        pop     rbp
        ret
Fiz::foo(int, int, int, int):
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], rdi
        mov     DWORD PTR [rbp-12], esi
        mov     DWORD PTR [rbp-16], edx
        mov     DWORD PTR [rbp-20], ecx
        mov     DWORD PTR [rbp-24], r8d
        nop
        pop     rbp
        ret
Buz::foo(int, int, int, int):
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], rdi
        mov     DWORD PTR [rbp-12], esi
        mov     DWORD PTR [rbp-16], edx
        mov     DWORD PTR [rbp-20], ecx
        mov     DWORD PTR [rbp-24], r8d
        nop
        pop     rbp
        ret
main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 32
        mov     eax, OFFSET FLAT:vtable for Bar+16
        mov     QWORD PTR [rbp-8], rax
        lea     rax, [rbp-8]
        mov     r8d, 4
        mov     ecx, 3
        mov     edx, 2
        mov     esi, 1
        mov     rdi, rax
        call    Bar::foo(int, int, int, int)
        mov     eax, OFFSET FLAT:vtable for Baz+16
        mov     QWORD PTR [rbp-16], rax
        lea     rax, [rbp-16]
        mov     r8d, 0
        mov     ecx, 7
        mov     edx, 6
        mov     esi, 5
        mov     rdi, rax
        call    Baz::foo(int, int, int, int)
        mov     eax, OFFSET FLAT:vtable for Fiz+16
        mov     QWORD PTR [rbp-24], rax
        lea     rax, [rbp-24]
        mov     r8d, 0
        mov     ecx, 0
        mov     edx, 9
        mov     esi, 8
        mov     rdi, rax
        call    Fiz::foo(int, int, int, int)
        mov     eax, OFFSET FLAT:vtable for Buz+16
        mov     QWORD PTR [rbp-32], rax
        lea     rax, [rbp-32]
        mov     r8d, 0
        mov     ecx, 0
        mov     edx, 0
        mov     esi, 10
        mov     rdi, rax
        call    Buz::foo(int, int, int, int)
        mov     eax, 0
        leave
        ret
vtable for Buz:
        .quad   0
        .quad   typeinfo for Buz
        .quad   Buz::foo(int, int, int, int)
vtable for Fiz:
        .quad   0
        .quad   typeinfo for Fiz
        .quad   Fiz::foo(int, int, int, int)
vtable for Baz:
        .quad   0
        .quad   typeinfo for Baz
        .quad   Baz::foo(int, int, int, int)
vtable for Bar:
        .quad   0
        .quad   typeinfo for Bar
        .quad   Bar::foo(int, int, int, int)
typeinfo for Buz:
        .quad   vtable for __cxxabiv1::__si_class_type_info+16
        .quad   typeinfo name for Buz
        .quad   typeinfo for Base
typeinfo name for Buz:
        .string "3Buz"
typeinfo for Fiz:
        .quad   vtable for __cxxabiv1::__si_class_type_info+16
        .quad   typeinfo name for Fiz
        .quad   typeinfo for Base
typeinfo name for Fiz:
        .string "3Fiz"
typeinfo for Baz:
        .quad   vtable for __cxxabiv1::__si_class_type_info+16
        .quad   typeinfo name for Baz
        .quad   typeinfo for Base
typeinfo name for Baz:
        .string "3Baz"
typeinfo for Bar:
        .quad   vtable for __cxxabiv1::__si_class_type_info+16
        .quad   typeinfo name for Bar
        .quad   typeinfo for Base
typeinfo name for Bar:
        .string "3Bar"
typeinfo for Base:
        .quad   vtable for __cxxabiv1::__class_type_info+16
        .quad   typeinfo name for Base
typeinfo name for Base:
        .string "4Base"
class Base {
public:
    virtual void foo(int a, double b, char c) = 0;
};

class Bar : public Base {
public:
    virtual void foo(int a, double b, char c) override { } // uses all three
};

class Baz : public Base {
public:
    virtual void foo(int a, double b, char c = '') override {} // uses only the int and double
};

class Biz : public Base {
public:
    virtual void foo(int a, double = 0.0, char c = '') override{} // uses only the int
};