【问题标题】:C++ - Overriden method not called properly (memory violation)C++ - 未正确调用覆盖的方法(内存冲突)
【发布时间】:2022-01-17 09:06:53
【问题描述】:

在我的程序中,我正在尝试创建名为“DMA”的抽象类,“BaseDMA”从中继承。然后类“LacksDMA”和“HasDMA”继承自“BaseDMA”。 每个类覆盖方法 readInfo() 来自“DMA”。代码如下:

dma.h

#ifndef DMA_H_
#define DMA_H_

#include <iostream>

class DMA
{
    protected:
        char * label;
    public:
        DMA(const char * l); 
        DMA & operator=(const DMA & anotherDMA);
        virtual ~DMA();
        virtual void readInfo() const = 0;
        char * getLabel() const ;
};

class BaseDMA: public DMA
{
    private: 
        int rating;
    public:
        BaseDMA(const char * l,  int r = 0);
        BaseDMA(const BaseDMA & anotherBaseDMA);
        virtual ~BaseDMA();
        BaseDMA & operator=(const BaseDMA & anotherBaseDMA);
        void readInfo() const override;
};

class LacksDMA: public BaseDMA
{
    private:
        enum { COL_LEN = 40 };
        char color[COL_LEN];
    public:
        LacksDMA(const char * c = "no color", const char * l = "no color", int r = 0);
        LacksDMA(const LacksDMA & anotherLacksDMA);
        LacksDMA & operator=(const LacksDMA & anotherLacksDMA);
        void readInfo() const override;
};

class HasDMA: public BaseDMA
{
    private:
        char * style;
    public:
        HasDMA(const char * s = "lack", const char * l = "lack", int r = 0);
        HasDMA(const HasDMA & anotherHasDMA);
        ~HasDMA();
        HasDMA & operator=(const HasDMA & anotherHasDMA);
        void readInfo() const override;
};

#endif DMA_H_

dma.cpp

#include <string.h>

DMA::DMA(const char * l)
{
    this->label = new char[strlen(l)+1];
    strcpy(this->label, l);
}


DMA & DMA::operator=(const DMA & anotherDMA)
{
    if(this == &anotherDMA)
        return * this;
    delete [] this->label;
    this->label = new char[strlen(anotherDMA.label)+1];
    strcpy(this->label, anotherDMA.label);
    return *this;
}

char * DMA::getLabel() const
{
    return this->getLabel();
}

DMA::~DMA()
{ 
    delete [] label;
}

BaseDMA::BaseDMA(const char * l,  int r)
    : DMA(l)
{
    this->rating = r;
}

BaseDMA::BaseDMA( const BaseDMA & anotherBaseDMA)
    : DMA(anotherBaseDMA.label)
{
    this->rating = anotherBaseDMA.rating;
}

BaseDMA::~BaseDMA()
{

} 

BaseDMA & BaseDMA::operator=(const BaseDMA & anotherBaseDMA)
{
    if(this == &anotherBaseDMA)
        return *this;
    DMA::operator=(anotherBaseDMA);
    this->rating = anotherBaseDMA.rating;
    return *this;
}

void BaseDMA::readInfo() const
{
   std::cout << "BaseDMA object:\n";
   std::cout << "Label: " << this->getLabel() << std::endl;
   std::cout << "Rating: " << this->rating << std::endl;
}


LacksDMA::LacksDMA(const char * c, const char * l, int r)
    :BaseDMA(l,r)
{
    strcpy(this->color, c);
}

LacksDMA::LacksDMA(const LacksDMA & anotherLacksDMA)
    : BaseDMA(anotherLacksDMA)
{
    strcpy(this->color, anotherLacksDMA.color);
}

LacksDMA & LacksDMA::operator=(const LacksDMA & anotherLacksDMA)
{
    if(this == &anotherLacksDMA)
        return *this;
    DMA::operator=(anotherLacksDMA);
    strcpy(this->color, anotherLacksDMA.color);
    return * this;
}

void LacksDMA::readInfo() const
{
    BaseDMA::readInfo();
    std::cout << "LacksDMA object:\n";
    std::cout << "Color: " << color << std::endl;
}

HasDMA::HasDMA(const char * s, const char * l, int r)
    :BaseDMA(l, r)
{
    this->style = new char[strlen(s)+1];
    strcpy(this->style, s);
}

HasDMA::HasDMA(const HasDMA & anotherHasDMA)
    :BaseDMA(anotherHasDMA)
{
    this->style = new char[strlen(anotherHasDMA.style)+1];
    strcpy(this->style, anotherHasDMA.style);
}

HasDMA::~HasDMA()
{
    delete [] this->style;
}

HasDMA & HasDMA::operator=(const HasDMA & anotherHasDMA)
{
    if(this == &anotherHasDMA)
        return *this;
    BaseDMA::operator=(anotherHasDMA);
    delete [] this->style;
    this->style = new char[strlen(anotherHasDMA.style)+1];
    strcpy(this->style, anotherHasDMA.style);
    return *this;
}
void HasDMA::readInfo() const
{
    BaseDMA::readInfo();
    std::cout << "HasDMA object:\n";
    std::cout << "Style: " << this->style << std::endl;

}

main.cpp

#include "dma.h"

void menuPanel();
void printDMS(DMA ** dms, int count);
int main()
{
    const int DMA_COUNT = 4;
    DMA * dmas[DMA_COUNT]; 
    for(int i = 0; i < DMA_COUNT; i++)
    {
        void menuPanel();
        int choice;
        do
        {
            (std::cin >> choice).ignore();
            if(std::cin.bad())
                std::cin.clear();
        } while (choice < 1 || choice > 3);
        
        std::cout << "Write label: ";
        char label[40];
        std::cin.getline(label, 40);
        std::cout << "Write rating: ";
        int rating;
        (std::cin >> rating).ignore();
        if(choice == 1)
        {
            dmas[i] = new BaseDMA(label,rating);
            std::cout << std::endl;
        }
        else if(choice == 2)
        {
            std::cout << "Write color: ";
            char color[40];
            std::cin.getline(color,40);
            dmas[i] = new LacksDMA(color, label, rating);
        }
        else // choice == 3
        {
            std::cout << "write style: ";
            char style[40];
            std::cin.getline(style,40);
            dmas[i] = new HasDMA(style, label, rating);
        }
    }
    for(int i = 0; i < DMA_COUNT; i++)
        delete dmas[i];
    
}

void menuPanel()
{
    std::cout << "Panel action:\n";
    std::cout << "1) make BbaseDMA" << std::endl;
    std::cout << "2) make LacksDMA" << std::endl;
    std::cout << "3) make HasDMA" << std::endl;
    std::cout << std::endl;
}

void printDMS(DMA **  dms, int count)
{
    for(int i = 0; i < count; i++)
    {
        dms[i]->readInfo();
        std::cout << std::endl;
    }
}

当我尝试通过在main() 中调用readInfo() 方法来使用运行时多态性时,我收到有关内存冲突的消息。 我做错了什么? 提前感谢您的回答。

【问题讨论】:

  • 你是不是忘记了某个虚拟的地方?
  • @Abel 是的,在覆盖的方法中,我忘记添加“虚拟”关键字。我现在添加了它们,但成功运行程序仍然没有任何进展。
  • virtual 添加到被覆盖的方法实际上并没有做任何事情,编译器只是忽略它。一旦基方法被标记为virtual,所有派生的覆盖都是隐式虚拟的。
  • 请注意DMA 缺少复制构造函数,因此破坏了Rule of 3。而LacksDMA(const char *, const char *, int) 构造函数中的strcpy() 是等待发生的缓冲区溢出。您是否有理由到处使用char* 而不是使用std::string?如果您使用std::string 并让它为您处理所有内存管理,则可以消除您展示的大部分类逻辑。
  • 你说调用readInfo()时会出现问题,但是我看到的对readInfo()的唯一调用是在printDMS()中,main()实际上并没有调用(main()没有调用menuPanel(),或者)。

标签: c++ inheritance overriding abstract


【解决方案1】:

您的代码存在许多问题,但您的内存问题就在这里:

char * DMA::getLabel() const
{
    return this->getLabel();
}

一旦调用getLabel(),例如在BaseDMA::readInfo(),您就会进入一个无限递归循环,最终溢出调用堆栈。

DMA::getLabel() 应该返回 this-&gt;label

char * DMA::getLabel() const
{
    return this->label;
}

【讨论】:

  • 是的,非常感谢。昨天我怎么看不到我一直在进行递归调用,这真的很令人不安。我还在 BaseDMA 中添加了复制构造函数(三规则),并纠正了 main.cpp 中的一些错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多