C++ void*不是指针对象/强制转换实现

C++ void*不是指针对象/强制转换实现,c++,c++11,casting,void-pointers,C++,C++11,Casting,Void Pointers,根据下面的代码,我正在尝试创建一个课程评分系统。因此,它将存储作业类型、权重和获得的分数。我试图让它打印原始分数(这是输入的分数,例如:“B-”或85.50;取决于它是考试还是测验) 我已经读过关于“casting”的内容,它应该解决使用void*作为指针的问题,但我仍然不清楚如何实现它。我尝试了static\u cast(c.gs[0])(在代码中注释掉),但它仍然返回值的地址,而不是值本身。任何帮助都将不胜感激。提前谢谢 #include <iostream> #include

根据下面的代码,我正在尝试创建一个课程评分系统。因此,它将存储作业类型、权重和获得的分数。我试图让它打印原始分数(这是输入的分数,例如:“B-”或85.50;取决于它是考试还是测验)

我已经读过关于“casting”的内容,它应该解决使用
void*
作为指针的问题,但我仍然不清楚如何实现它。我尝试了
static\u cast(c.gs[0])
(在代码中注释掉),但它仍然返回值的地址,而不是值本身。任何帮助都将不胜感激。提前谢谢

#include <iostream>
#include <vector>
using namespace std;

struct Grading{
    string name;
    int percentage;
    virtual ~Grading(){}
    virtual void* get_raw_score(){return 0;}
    void* get_adj_score(){return 0;}
};

struct Quiz:public Grading{
    string letter_grade;
    Quiz(const string title, const int weight, const string grade){
        name=title;
        percentage=weight;
        letter_grade=grade;
    }
    virtual void* get_raw_score(){return &letter_grade;}
};

struct Exam:public Grading{
    double *score = new double;
    Exam(const string title, const int weight, const double grade){
        name=title;
        percentage=weight;
        *score=grade;
    }
    virtual void* get_raw_score(){return &score;}
};

struct Project:public Grading{
    string letter_grade;
    Project(const string title, const int weight, const string grade){
        name=title;
        percentage=weight;
        letter_grade=grade;
    }
    virtual void* get_raw_score(){return &letter_grade;}
};

struct CourseWork{
    vector<Grading*> gs;
    void push_back(Grading* g){
        gs.push_back(g);
    }
    void sort_name(){}
    void sort_score(){}
};

ostream& operator<<(ostream& o,const CourseWork c){ //output the raw score here.
 //static_cast<struct Grading*>(c.gs[0]);
    o<<c.gs[0]->name<<endl<<c.gs[0]->percentage<<c.gs[0]->get_raw_score()<<endl;
    return o;
}

int main() {

    CourseWork c;

    c.push_back(new Quiz("Quiz", 5, "B-"));
    c.push_back(new Quiz("Quiz", 5, "C+"));
    c.push_back(new Quiz("Quiz", 5, "A"));
    c.push_back(new Exam("Midterm", 10, 50));
    c.push_back(new Exam("Final", 30, 85.5));
    c.push_back(new Project("Project", 5, "A-"));
    c.push_back(new Project("Project", 15, "B-"));
    c.push_back(new Project("Project", 15, "B-"));
    c.push_back(new Project("Demo", 10, "C"));

    cout << "** Showing populated data..." << endl;
    cout << c << endl << endl;;

    c.sort_name();
    cout << "** Showing sorted by name..." << endl;
    cout << c << endl << endl;

    c.sort_score();
    cout << "** Showing sorted by score..." << endl;
    cout << c << endl;

    return 0;
}
#包括
#包括
使用名称空间std;
结构分级{
字符串名;
整数百分比;
虚拟~Grading(){}
虚拟空*获取原始分数(){return 0;}
void*get_adj_score(){return 0;}
};
结构测验:公开评分{
字符串字母_级;
测验(常量字符串标题、常量整数权重、常量字符串等级){
姓名=头衔;
百分比=重量;
字母\等级=等级;
}
虚拟无效*获取原始分数(){return&letter\u grade;}
};
结构考试:公开评分{
双倍*分数=新的双倍;
考试(常数字符串标题、常数整数权重、常数双级){
姓名=头衔;
百分比=重量;
*分数=等级;
}
虚拟空*获取原始分数(){return&score;}
};
结构项目:公共放坡{
字符串字母_级;
项目(常量字符串标题、常量整数权重、常量字符串等级){
姓名=头衔;
百分比=重量;
字母\等级=等级;
}
虚拟无效*获取原始分数(){return&letter\u grade;}
};
结构课程{
载体gs;
无效推回(放坡*g){
gs.推回(g);
}
void sort_name(){}
无效排序_分数(){}
};

ostream&operator不必编写返回一个
void*
的函数,并尝试找出它实际返回的内容,您可以让函数在所有情况下都返回一个字符串,但当它是一个数字时,只需将数字转换为字符串即可。您可以使用:

struct Grading{
    string name;
    int percentage;
    virtual ~Grading(){}
    virtual std::string get_raw_score() = 0; //make pure virtual since we only use Grading as a base class
    void* get_adj_score(){return 0;}
};

struct Quiz:public Grading{
    string letter_grade;
    Quiz(const string title, const int weight, const string grade){
        name=title;
        percentage=weight;
        letter_grade=grade;
    }
    virtual std::string get_raw_score(){return letter_grade;}
};

struct Exam:public Grading{
    double score; // this does not need to be a pointer
    Exam(const string title, const int weight, const double grade){
        name=title;
        percentage=weight;
        score=grade; // no more dereference
    }
    virtual std::string get_raw_score(){return std::stod(score);} // now the score is represented as a string
};

struct Project:public Grading{
    string letter_grade;
    Project(const string title, const int weight, const string grade){
        name=title;
        percentage=weight;
        letter_grade=grade;
    }
    virtual std::string get_raw_score(){return letter_grade;}
};

struct CourseWork{
    vector<Grading*> gs;
    void push_back(Grading* g){
        gs.push_back(g);
    }
    void sort_name(){}
    void sort_score(){}
};

ostream& operator<<(ostream& o,const CourseWork c){ //output the raw score here.
 //static_cast<struct Grading*>(c.gs[0]);
    o<<c.gs[0]->name<<endl<<c.gs[0]->percentage<<c.gs[0]->get_raw_score()<<endl;
    return o;
}
struct放坡{
字符串名;
整数百分比;
虚拟~Grading(){}
virtual std::string get_raw_score()=0;//使纯虚拟化,因为我们只将分级用作基类
void*get_adj_score(){return 0;}
};
结构测验:公开评分{
字符串字母_级;
测验(常量字符串标题、常量整数权重、常量字符串等级){
姓名=头衔;
百分比=重量;
字母\等级=等级;
}
虚拟std::string get_raw_score(){return letter_grade;}
};
结构考试:公开评分{
double score;//这不需要是指针
考试(常数字符串标题、常数整数权重、常数双级){
姓名=头衔;
百分比=重量;
分数=等级;//不再取消引用
}
虚拟std::string get_raw_score(){return std::stod(score);}//现在分数表示为字符串
};
结构项目:公共放坡{
字符串字母_级;
项目(常量字符串标题、常量整数权重、常量字符串等级){
姓名=头衔;
百分比=重量;
字母\等级=等级;
}
虚拟std::string get_raw_score(){return letter_grade;}
};
结构课程{
载体gs;
无效推回(放坡*g){
gs.推回(g);
}
void sort_name(){}
无效排序_分数(){}
};

ostream&operator不必编写返回一个
void*
的函数,并尝试找出它实际返回的内容,您可以让函数在所有情况下都返回一个字符串,但当它是一个数字时,只需将数字转换为字符串即可。您可以使用:

struct Grading{
    string name;
    int percentage;
    virtual ~Grading(){}
    virtual std::string get_raw_score() = 0; //make pure virtual since we only use Grading as a base class
    void* get_adj_score(){return 0;}
};

struct Quiz:public Grading{
    string letter_grade;
    Quiz(const string title, const int weight, const string grade){
        name=title;
        percentage=weight;
        letter_grade=grade;
    }
    virtual std::string get_raw_score(){return letter_grade;}
};

struct Exam:public Grading{
    double score; // this does not need to be a pointer
    Exam(const string title, const int weight, const double grade){
        name=title;
        percentage=weight;
        score=grade; // no more dereference
    }
    virtual std::string get_raw_score(){return std::stod(score);} // now the score is represented as a string
};

struct Project:public Grading{
    string letter_grade;
    Project(const string title, const int weight, const string grade){
        name=title;
        percentage=weight;
        letter_grade=grade;
    }
    virtual std::string get_raw_score(){return letter_grade;}
};

struct CourseWork{
    vector<Grading*> gs;
    void push_back(Grading* g){
        gs.push_back(g);
    }
    void sort_name(){}
    void sort_score(){}
};

ostream& operator<<(ostream& o,const CourseWork c){ //output the raw score here.
 //static_cast<struct Grading*>(c.gs[0]);
    o<<c.gs[0]->name<<endl<<c.gs[0]->percentage<<c.gs[0]->get_raw_score()<<endl;
    return o;
}
struct放坡{
字符串名;
整数百分比;
虚拟~Grading(){}
virtual std::string get_raw_score()=0;//使纯虚拟化,因为我们只将分级用作基类
void*get_adj_score(){return 0;}
};
结构测验:公开评分{
字符串字母_级;
测验(常量字符串标题、常量整数权重、常量字符串等级){
姓名=头衔;
百分比=重量;
字母\等级=等级;
}
虚拟std::string get_raw_score(){return letter_grade;}
};
结构考试:公开评分{
double score;//这不需要是指针
考试(常数字符串标题、常数整数权重、常数双级){
姓名=头衔;
百分比=重量;
分数=等级;//不再取消引用
}
虚拟std::string get_raw_score(){return std::stod(score);}//现在分数表示为字符串
};
结构项目:公共放坡{
字符串字母_级;
项目(常量字符串标题、常量整数权重、常量字符串等级){
姓名=头衔;
百分比=重量;
字母\等级=等级;
}
虚拟std::string get_raw_score(){return letter_grade;}
};
结构课程{
载体gs;
无效推回(放坡*g){
gs.推回(g);
}
void sort_name(){}
无效排序_分数(){}
};

ostream&operator您可以将基类抽象化,并使用模板参数,而不是使用
void*
指针:

struct IGrading {
     virtual const std::string get_raw_score() const = 0;
};

template<typename T>
class Grading : public IGrading {
public:
     virtual ~Grading() {}
};

std::ostream& operator<<(std::ostream& os, const IGrading& g) {
    os << g.get_raw_score();
    return os;
}
这将保证您的代码类型安全,并避免任何奇怪和容易出错的强制转换操作

课程作业
容器可以使用抽象界面:

struct CourseWork{
    vector<IGrading*> gs;
    void push_back(IGrading* g){
        gs.push_back(g);
    }
    void sort_name(){}
    void sort_score(){}
};
struct课程作业{
载体gs;
无效推回(IGrading*g){
gs.推回(g);
}
void sort_name(){}
无效排序_分数(){}
};

您可以将基类抽象化,并使用模板参数而不是使用
void*
指针:

struct IGrading {
     virtual const std::string get_raw_score() const = 0;
};

template<typename T>
class Grading : public IGrading {
public:
     virtual ~Grading() {}
};

std::ostream& operator<<(std::ostream& os, const IGrading& g) {
    os << g.get_raw_score();
    return os;
}
这将保证您的代码类型安全,并避免任何奇怪和容易出错的强制转换操作

课程作业
容器可以使用抽象界面:

struct CourseWork{
    vector<IGrading*> gs;
    void push_back(IGrading* g){
        gs.push_back(g);
    }
    void sort_name(){}
    void sort_score(){}
};
struct课程作业{
载体gs;
无效推回(IGrading*g){
gs.推回(g);
}
void sort_name(){}
无效排序_分数(){}
};

根据我所做的阅读,这是获得
字符串
双精度
的唯一方法,因为如果
struct CourseWork{
    vector<IGrading*> gs;
    void push_back(IGrading* g){
        gs.push_back(g);
    }
    void sort_name(){}
    void sort_score(){}
};