首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在C++中调用从基变量派生的函数?

如何在C++中调用从基变量派生的函数?
EN

Stack Overflow用户
提问于 2021-04-09 02:56:24
回答 3查看 90关注 0票数 0

我目前正在处理一个类,以及从这个基类派生出来的其他三个类。基类本质上应该是抽象的,因此我可以调用基类的虚拟函数,并让它执行派生类的预期函数。我的最终目标是做这样的事情:

代码语言:javascript
复制
class Car {
public:
    virtual void drive() = 0;  // Pure-virtual function
};

class Ford : public Car {
public:
    virtual void drive() { std::cout << "driving Ford\n"; }
};

这应该能行。在空文件中,此设置可以工作。我的实现肯定是错误的,但是c++编译器并没有给我任何关于错误是什么的好提示。

目前,我正在使用一个函数来创建派生类,返回要在main中使用的基类。我已经试过了所有我能想到的:

  • 传入的指针在退出
  • 后不会被销毁,返回派生类并存储到基类
  • 中,将基类/指针转换为派生类
  • ,设置指向派生类

<代码>F 210的取消引用的基类指针

我只是无法让它为我的生命工作。当从基类变量运行时,虚拟函数只会导致seg错误。下面是我认为与当前状态相关的所有代码,因为我正在测试。

H:

代码语言:javascript
复制
class Instruction {
    public:
        virtual void print(){};
        bool operator==(const int& rhs) const;
        void writeBack();
        void memory();
        virtual void execute(long registers[32], long dmem[32]){};
        unsigned int str2int(const char *str, int h);
        virtual ~Instruction(){};
};

ITypeInstruction.h:

代码语言:javascript
复制
class IType: public Instruction {
    private:
        int op;
        string label;
        string rs;
        string rt;
        string immediate;
        map<string, string> registerMap;

    public:
        IType(int op, string label);
        IType(int op, string label, string rs, string rt, string immediate, map<string, string> registerMap);
        virtual void print();
        void execute(long registers[32], long dmem[32]);
};

ITypeInstruction.cpp:

代码语言:javascript
复制
void IType::print()
{
    cout << "Instruction Type: I " << endl;
    cout << "Operation: " << label << endl;
    cout << "Rs: " << registerMap[rs] << " (R" << rs << ")" << endl;
    cout << "Rt: " << registerMap[rt] << " (R" << rt << ")" << endl;
    cout << "Immediate: 0x" << immediate << endl;
}

Decode.cpp:

代码语言:javascript
复制
Instruction *decode(string binaryIn, map<string, string> registerSet, map<string, string> instructionSet, Instruction *instructionPointer)
{
        IType ins = IType(opcode, label, rs, rt, imm, registerSet);
        Instruction i = IType(opcode, label, rs, rt, imm, registerSet);
        ins.print();
        *instructionPointer = ins;
        (*instructionPointer).print();
        return instructionPointer;
}

main.cpp

代码语言:javascript
复制
Instruction *instructionToExecute;
instructionToExecute = decode(instructionToDecode, registerSet, instructionSet, instructionToExecute);
instructionToExecute->print();
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-04-09 03:05:44

您显示的代码有多个问题。

一个是尝试取消对未初始化的instructionPointer变量的引用。

另一个原因是*instructionPointer = ins;导致了。

相反,动态创建IType对象并返回指向该对象的指针:

代码语言:javascript
复制
Instruction *decode(string binaryIn, map<string, string> registerSet, map<string, string> instructionSet)
{
    return new IType(opcode, label, rs, rt, imm, registerSet);
}

请注意,instructionPointer参数不再存在。

票数 3
EN

Stack Overflow用户

发布于 2021-04-09 03:08:14

decode中,您将IType作为局部变量创建,在函数返回时导致它被销毁。

更多的C++风格

代码语言:javascript
复制
std::unique_ptr<Instruction>
decode(string binaryIn, map<string, string> registerSet, map<string, string> instructionSet)
{
  std::unique_ptr<Instruction> ins = std::make_unique<IType>(opcode, label, rs, rt, imm, registerSet);
  ins->print();
  return ins;
}

auto instructionToExecute = decode(...);
instructionToExecute->print();
票数 3
EN

Stack Overflow用户

发布于 2021-04-09 03:17:49

正确的方法是:

代码语言:javascript
复制
#include <memory>

std::unique_ptr<Instruction> decode(
    string binaryIn,
    map<string, string> registerSet,
    map<string, string> instructionSet,
    Instruction *instructionPointer)
{
  return std::make_unique<IType>(opcode, label, rs, rt, imm, registerSet);
}

int main() {
    // ...
    auto instructionToExecute = decode(instructionToDecode, registerSet,
        instructionSet, instructionToExecute);
    instructionToExecute->print();
}

正在发生的事情:函数中定义的变量(未标记为static)除了返回值外,不存在于该函数的末尾。您知道基类返回类型应该是指针,而不是基类类型,以避免切片,但随后需要某种方法来提供指向足以使用的对象的指针。std::make_unique是最简单的方法。

出了差错的事情:

代码语言:javascript
复制
Instruction *decode(string binaryIn, map<string, string> registerSet, map<string, string> instructionSet, Instruction *instructionPointer)
{
        // OK, but the object "ins" lives only until the function returns.
        IType ins = IType(opcode, label, rs, rt, imm, registerSet);

        // Immediately slices to the base class, and isn't an IType any more.
        Instruction i = IType(opcode, label, rs, rt, imm, registerSet);

        // No problem.
        ins.print();

        // This uses the operator= of the base class Instruction.
        // It's probably not going to be able to handle assigning derived info
        // well, even if instructionPointer does in fact point at the same
        // derived type.       
        *instructionPointer = ins;

        (*instructionPointer).print();

        // This will be just the same pointer as the passed argument,
        // so doesn't really add any utility.
        return instructionPointer;
}

int main() {
    // ...

    // This pointer is an uninitialized value. Using it is as bad as
    // using the value of an uninitialized "int v;"...
    Instruction *instructionToExecute;

    // Uh oh. decode does *instructionToExecute = something;
    // But instructionToExecute is uninitialized and doesn't actually
    // point at any object to reassign! (Not even a base type object.)
    instructionToExecute = decode(instructionToDecode, registerSet,
        instructionSet, instructionToExecute);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67014470

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档