指针为什么不写类的地址?

时间:2020-02-21 10:51:00

标签: c++

我有一个抽象类“ Mark”,有一个子类“ Int_num”。我也有一个“主题”课程。我希望在调用其构造函数时将指向“ Mark”类的内存中地址的指针写入“ mark”参数。在编译器抱怨“表达式必须具有类类型”或诸如在mark.print_mark()中类似的内容之后,发生了什么使标记指针指向“ Mark”类的事情?”

class Mark {
private:
    int mark;
public:
    virtual void change_mark(int);
    virtual void print_mark();
    virtual int return_mark();
};

class Int_mark : public Mark {
private:
    int mark;
public:
    Int_mark();
    Int_mark(int);
    ~Int_mark();

    void change_mark(int = 0);
    void print_mark() const;
    int return_mark() const;
};

Int_mark::Int_mark() {
    std::string str_mark;
    std::cout << "New mark: ";
    std::cin.ignore();
    std::getline(std::cin, str_mark);

    str_mark = ltrim(rtrim(str_mark));
    int new_mark;
    try {
        new_mark = stoi(str_mark);
    } catch(...) {
        std::cout <<"wq";
        mark = 1;
        return ;
    }

    try {
        if((new_mark < 1) || (new_mark > 5))
            throw 1;
        else
            mark = new_mark;
    } catch(int a) {
        std::cout << "qw" << std::endl;
        mark = 1;
    }
}
void Int_mark::print_mark() const {
    std::cout << "Mark: " << mark << std::endl;
}

主题

#include "Mark.h"
#include <string>
#include <vector>

class Subject {
private:
    std::string name_subject;
    std::string type_subject;
    unsigned hour_subject = 0;
    void *mark = nullptr;
public:
    Subject();
    Subject(std::string, int);
    Subject(std::string, bool);
    ~Subject();

    void change_mark(unsigned);
    void change_mark(bool);
    void rename_subj(std::string);
    void add_hour(unsigned);
};

Subject::Subject() {
    std::string name_sub;
    std::cout << "Введите название предмета: ";
    getline(std::cin, name_sub);
    name_sub = split_string(name_sub);
    name_subject = name_sub;
    int select = 2;

    if(select == 1) {
        type_subject = "Bool";
        //mark = new Bool_mark();
    } else {
        type_subject = "Int";    
        mark = new Int_mark();   


//What should I do to make the mark pointer point to the "Mark" class?
        mark.print_mark();

}
}

主要

#include "subject/Subject.h"

using namespace std;

int main() {
    Subject q;
}

我在做什么错?我该怎么办?

2 个答案:

答案 0 :(得分:1)

指针mark的类型为void *。你可以用

static_cast<Int_mark*>(mark)

并使用调用该函数

static_cast<Int_mark*>(mark)->print_mark();

但是通常在OOP mark中将是指向基类的指针

Mark *mark = nullptr;

现在,您可以使用

检查错误
mark = new Int_mark();   

auto *m = dynamic_cast<Int_mark*>(mark);

if (m)
    m->print_mark();

记住基类中的虚拟析构函数

virtual ~Mark();

When to use virtual destructors?

这是您代码的固定版本:

#include <iostream>
#include <string>
#include <vector>

class Mark {
public:
    virtual ~Mark() = default;

    //virtual void change_mark(int) = 0;
    virtual void print_mark() const = 0;
    //virtual int return_mark() const = 0;
};

class Int_mark : public Mark {
private:
    int mark;
public:
    Int_mark();
    Int_mark(int);
    ~Int_mark() override = default;

    //void change_mark(int = 0) override;
    void print_mark() const override;
    //int return_mark() const override;
};

Int_mark::Int_mark() {
    std::string str_mark;
    std::cout << "New mark: ";
    std::cin.ignore();
    std::getline(std::cin, str_mark);

    //str_mark = ltrim(rtrim(str_mark));
    int new_mark;
    try {
        new_mark = stoi(str_mark);
    } catch(...) {
        std::cout <<"wq";
        mark = 1;
        return ;
    }

    try {
        if((new_mark < 1) || (new_mark > 5))
            throw 1;
        else
            mark = new_mark;
    } catch(int a) {
        std::cout << "qw" << std::endl;
        mark = 1;
    }
}
void Int_mark::print_mark() const {
    std::cout << "Mark: " << mark << std::endl;
}

class Subject {
private:
    std::string name_subject;
    std::string type_subject;
    unsigned hour_subject = 0;
    Mark *mark = nullptr;
public:
    Subject();
    Subject(std::string, int);
    Subject(std::string, bool);
    ~Subject();

    void change_mark(unsigned);
    void change_mark(bool);
    void rename_subj(std::string);
    void add_hour(unsigned);
};

Subject::Subject() {
    std::string name_sub;
    std::cout << "Введите название предмета: ";
    getline(std::cin, name_sub);
    //name_sub = split_string(name_sub);
    name_subject = name_sub;
    int select = 2;

    if(select == 1) {
        type_subject = "Bool";
        //mark = new Bool_mark();
    } else {
        type_subject = "Int";    
        mark = new Int_mark();   

        auto *m = dynamic_cast<Int_mark*>(mark);
        if (m)
            m->print_mark();
    }
}

Subject::~Subject() {
    delete mark;
}

int main() {
    Subject q;
}

答案 1 :(得分:0)

由于我一开始对问题的理解不正确,因此介绍了一种如何通过派生类Mark的对象调用基类Int_Mark的成员函数的方法:

Int_mark *mark = new Int_mark();
mark->print_mark();       // calls member of the class Int_mark
mark->Mark::print_mark(); // calls member of the class Mark

确保也定义了Mark::print_mark(),而不仅仅是Int_mark::print_mark()