【问题标题】:Overriding Pure Virtual Functions from a Template Base Class从模板基类覆盖纯虚函数
【发布时间】:2017-06-28 05:43:22
【问题描述】:

所以我正在尝试制作一个基于数组的包,它的行为类似于堆栈,因为它添加到顶部,但它也可以检查和删除不在顶部的元素。

对于我的作业,我的教授给了我这个 bagADT 类模板,它带有纯虚函数。

#ifndef BAGADT_H
#define BAGADT_H

#include <stdlib.h>
#include "book.h"

template <typename E>
class Bag {
public:
    Bag() {}            // base constructor
    virtual ~Bag() {}   // base destructor
// Insert a new item into the bag -- return false if fails and true if
// successful
virtual bool addItem(const E& item) = 0;

// Looks for 'item' in the bag and if found updates 'item' with the 
// bag value and returns true.  Otherwise 'item' is left unchanged
// and the method returns false.
virtual bool remove(E& item) = 0;

// Removes the top record from the bag, puts it in returnValue, and
// returns true if the bag is not empty.  If the bag is empty the 
// function returns false and returnValue remains unchanged.
virtual bool removeTop(E& returnValue) = 0;

// Finds the record using returnValue and if the record is found updates
// returnValue based on the contents of the bag and returns true.  If the
// record is not found the function returns false.  Works just like remove()
// except that the found record is not removed from the bag.
virtual bool find(E& returnValue) const = 0;

// Inspect the top of the bag.  If the bag is empty return
// false and leave 'item' unchanged; otherwise, return true and update 
// 'item' with the contents of the bag.
virtual bool inspectTop(E& item) const = 0;

// empties the bag
virtual void emptyBag() = 0;

// use the += operator to add an item to the bag
virtual bool operator+=(const E& addend) = 0;

// get the size of the bag
virtual int size() const = 0;

// get the capacity of the bag
virtual int bagCapacity() const = 0;
};

#endif  /* BAGADT_H */

鉴于此,我创建了一个继承的 ABag 类。

#pragma once
#include "bagADT.h"


#ifndef ABAG_H
#define ABAG_H

template <typename E>
class ABag : public Bag<E>
{
public:
    ABag(int size = 10)
    {
        maxSize = size;
        top = 0;
        listArray = new E[size];
    }
     virtual ~ABag()
    {
        delete[] listArray;
    }

    template <typename E>
    bool addItem(const E& item)
    {
        if (top < maxSize)
        {
            listArray[top] = item;
            top++;
            return true;
        }
        else
            return false;

    }


    // Looks for 'item' in the bag and if found updates 'item' with the 
    // bag value and returns true.  Otherwise 'item' is left unchanged
    // and the method returns false.
    //template <typename E>
    bool remove(E& item)
    {
        for (int i = 0; i <= top; i++)
        {
            if (listArray[i] == item)
            {
                for (int j = i + 1; j <= top; j++)
                {
                    listArray[i] = listArray[j];
                    i++;
                }
                top--;
                return true;
            }
        }
        return false;
    }


    // Removes the top record from the bag, puts it in returnValue, and
    // returns true if the bag is not empty.  If the bag is empty the 
    // function returns false and returnValue remains unchanged.
    //template <typename E>
    bool removeTop(E& returnValue)
    {
        if (top > 0)
        {
            returnValue = listArray[top--];
        }


    }


    // Finds the record using returnValue and if the record is found updates
    // returnValue based on the contents of the bag and returns true.  If the
    // record is not found the function returns false.  Works just like remove()
    // except that the found record is not removed from the bag.
    //template <typename E>
    bool find(E& returnValue)
    {

    }

    // Inspect the top of the bag.  If the bag is empty return
    // false and leave 'item' unchanged; otherwise, return true and update 
    // 'item' with the contents of the bag.
    //template <typename E>
    bool inspectTop(E& item)
    {
        if (top != 0)
        {
            item = listArray[top];
            return true;
        }
        else
            return false;
    }

    // empties the bag
    //template <typename E>
    void emptyBag()
    {
        top = 0;
    }

    // use the += operator to add an item to the bag
    //template <typename E>
    bool operator+=(const E& addEnd)
    {

    }

    // get the size of the bag
    //template <typename E>
    int size()
    {
        return top;
    }

    // get the capacity of the bag
    //template <typename E>
    int bagCapacity()
    {
        return maxSize;
    }

private:
    int maxSize;
    int top;
    E *listArray;
};


/*template <typename E>
ABag<E>::ABag()
{
    int size = 10
    maxSize = size;
    top = 0;
    listArray = new E[size];
}


template <typename E>
ABag<E>::~ABag()
{
    delete [] listArray;
}*/
#endif

这是我的 source.cpp 试图从类中实例化一个对象。

#include <iostream>
#include <string>
#include "ABag.h"
#include "BDictionary.h"

using namespace std;

int main(){
    ABag<int> myBag;

    cout << myBag.bagCapacity();

    system("Pause");
    return 0;
}

而且出于某种原因。我不断收到此错误。

error C2259: 'ABag<int>' : cannot instantiate abstract class

一个又一个论坛,我在堆栈交换、教科书和论坛中跋涉,试图弄清楚为什么这不起作用。我明白错误是什么。我知道你不能从抽象类中创建一个对象。但是我已经尝试了十几种不同的方法来尝试覆盖基类中的纯虚函数,但我做不到。有一个 IntelliSense 错误告诉我每个纯虚函数都没有覆盖器。

谁能帮帮我?

【问题讨论】:

  • 我要做的第一件事就是在class ABag 中丢失addItem 上面的template &lt;typename E&gt;。它不属于那里,并隐藏类模板参数。您至少应该收到有关它的警告。除此之外,您将const 和非常量成员国从基础到派生的混合当然也无济于事。例如:find 在您的基础中声明为 const,但在您的派生中没有。
  • 我把它注释掉了,我仍然得到同样的错误。我没有收到关于它的警告。此外,每当我尝试在派生类中的继承函数上使用 const 时,我都会收到一条错误消息,指出我不能在非成员函数上使用修饰符
  • 阅读该评论的第二部分。您的基础中有大量成员 const,而不是派生中的成员。它们必须匹配 整个 签名,包括 const-ness。
  • 尝试编译完整的警告-Wall -Wextra -pedantic,看看你收到了什么警告。我看到了一些关于 hiding 功能的信息。使用 override 关键字将这些警告变成错误。
  • 没关系。到目前为止,我用 const 修复了它。我觉得自己像个哑巴**

标签: c++ inheritance pure-virtual


【解决方案1】:

这就是问题所在:

template <typename E>
bool addItem(const E& item)
{
    if (top < maxSize)
    {
        listArray[top] = item;
        top++;
        return true;
    }
    else
        return false;

}

你看,抽象类C 的任何子类D 本身都被认为是抽象的,除非D 绝对实现了C 的所有纯虚方法。 Bag&lt;E&gt;addItem() 是一个带有签名bool Bag&lt;E&gt;::addItem( const E&amp; ) 的纯虚函数。另一方面,ABag&lt;E&gt;addItem() 是一个函数template,它接受一个名为E 的类型模板参数,它会影响ABag&lt;E&gt; 中的另一个E。一旦实例化,就会产生一个签名为bool ABag&lt;E1&gt;::addItem&lt;E2&gt;( const E2&amp; )的函数。

这里的重要一点是函数模板与函数不同。您可以将函数模板实例化为函数,但这两个概念本身是不兼容的。 ABag&lt;E&gt; 中的函数模板没有实现 Bag&lt;E&gt; 中相应的纯虚函数,因为它们的签名本质上是不兼容的。当您不匹配constness 时也会发生这种情况。带有签名void foo( int ) 的函数void foo( int ) const 兼容。前者在任何情况下都不会覆盖/实现后者。

【讨论】:

  • 谢谢你!到目前为止它起作用了。不仅如此,我没有基类拥有的'const'关键字。我不能感谢你们足够的
猜你喜欢
  • 2014-03-08
  • 2014-08-16
  • 2013-10-04
  • 2021-09-30
  • 2021-11-08
  • 2020-08-21
  • 1970-01-01
  • 1970-01-01
  • 2022-01-13
相关资源
最近更新 更多