用C++定义一个人员类

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用C++定义一个人员类相关的知识,希望对你有一定的参考价值。

Person,它有姓名、性别、身份证号、出生日期等信息,同时拥有
能够显示和设置这些信息的函数;从
Person类派生出学生类
Student和教师类
Teacher,学
生类有学号、年级、班级等信息,教师类有职称等信息;再从
Student和
Teacher类派生出
在职学习的教师类
StuTeacher。以上类中的信息采用动态内存分配存储的方法,要在构造函
数里分配存储空间,要有析构函数释放空间,要有拷贝构造函数实现深拷贝。在类的继承关
系中要合理利用虚拟继承避免二义性问题,要在派生类中重写基类中继承来的成员函数。类
中的其它内容自行设计,编写测试代码使用这些类。

main函数自己写吧

#include <stdlib.h>
#include <iostream>
using namespace std;

class Person

public:
Person()

name = new char[10];
sex = new char[6];
num = new char[20];
birthday = new char[8];


~Person()

delete[] name;
delete[] sex;
delete[] num;
delete[] birthday;


Person(Person &p)

if(strlen(name) != strlen(p.name))
name = new char[strlen(p.name) + 1];
if(strlen(sex) != strlen(p.sex))
sex = new char[strlen(p.sex) + 1];
if(strlen(num) != strlen(p.num))
num = new char[strlen(p.num) + 1];
if(strlen(birthday) != strlen(p.birthday))
birthday = new char[strlen(p.birthday) + 1];
if(this != &p)
strcpy(name, p.name);
strcpy(sex, p.sex);
strcpy(num, p.num);
strcpy(birthday, p.birthday);


void setInfo(char *name, char *sex, char *num, char *birthday)

strcpy(this->name, name);
strcpy(this->sex, sex);
strcpy(this->num, num);
strcpy(this->birthday, birthday);


virtual void getInfo()

cout << "In Person class" << endl;
cout << "Name: " << name << endl;
cout << "Sex: " << sex << endl;
cout << "Number: " << num << endl;
cout << "Brithday: " << birthday << endl;


protected:
char *name;
char *sex;
char *num;
char *birthday;
;

class Student : public virtual Person

public:
Student()

snum = new char[5];
grade = new char[5];
sclass = new char[5];


~Student()

delete[] snum;
delete[] grade;
delete[] sclass;


Student(Student &s)

if(strlen(snum) != strlen(s.snum))
snum = new char[strlen(s.snum) + 1];
if(strlen(grade) != strlen(s.grade))
grade = new char[strlen(s.grade) + 1];
if(strlen(sclass) != strlen(s.sclass))
sclass = new char[strlen(s.sclass) + 1];
if(this != &s)
strcpy(snum, s.snum);
strcpy(grade, s.grade);
strcpy(sclass, s.sclass);


void getInfo()

cout << "In Student class" << endl;
cout << "Student number: " << snum << endl;
cout << "Grade: " << grade << endl;
cout << "Class: " << sclass << endl;


protected:
char *snum;
char *grade;
char *sclass;
;

class Teacher : public virtual Person

public:
Teacher()

title = new char[20];


~Teacher()

delete[] title;


Teacher(Teacher &t)

if(strlen(title) != strlen(t.title))
title = new char[strlen(t.title) + 1];
if(this != &t)
strcpy(title, t.title);


protected:
char *title;
;

class StuTeacher : public Student, public Teacher

;
参考技术A 你是指对象实例的this指针还是一个普通变量?如果是普通的局部变量(在栈中分配内存的)返回地址也没用的,会在函数执行完之后销毁的。本回答被提问者采纳

使用 DLL 覆盖/修改 C++ 类

【中文标题】使用 DLL 覆盖/修改 C++ 类【英文标题】:Overriding / modifying C++ classes using DLLs 【发布时间】:2009-08-17 18:06:31 【问题描述】:

我有一个项目,我维护的代码库很大(>200,000 行代码)(“核心”)。

目前,这个核心有一个脚本引擎,它由钩子和一个脚本管理器类组成,当它们发生时调用所有钩子函数(通过 DLL 注册的函数)。老实说,我不知道它究竟是如何工作的,因为核心大多没有文档记录,并且跨越数年和大量开发人员(当然,他们不存在)。当前脚本引擎的一个例子是:

void OnMapLoad(uint32 MapID)

    if (MapID == 1234)
    
        printf("Map 1234 has been loaded");
    


void SetupOnMapLoad(ScriptMgr *mgr)

    mgr->register_hook(HOOK_ON_MAP_LOAD, (void*)&OnMapLoad);

一个名为setup.cpp 的补充文件调用SetupOnMapLoad 与核心的ScriptMgr

这种方法不是我要找的。对我来说,完美的脚本引擎将允许我覆盖核心类方法。我希望能够创建从核心类继承并对其进行扩展的类,如下所示:

// In the core:    
class Map

    uint32 m_mapid;
    void Load();
    //...


// In the script:
class ExtendedMap : Map

    void Load()
    
        if (m_mapid == 1234)
            printf("Map 1234 has been loaded");

        Map::Load();
    

然后我希望核心和脚本中的每个Map 实例实际上都是ExtendedMap 的实例。

这可能吗?怎么样?

【问题讨论】:

【参考方案1】:

继承是可能的。我没有看到用 ExtendedMap 实例替换 Map 实例的解决方案。

通常,如果您有一个始终用于创建 Map 对象的工厂类或函数,则可以这样做,但这是现有(或不存在)设计的问题。

我看到的唯一解决方案是在代码中搜索实例化并尝试手动替换它们。这是一个有风险的做法,因为您可能会错过其中的一些,并且可能是某些实例不在您可用的源代码中(例如,在那个旧 DLL 中)。

稍后编辑 在以多态方式使用它时,这种方法覆盖也有副作用。

例子:

Map* pMyMap = new ExtendedMap; 

pMyMap->Load(); // This will call Map::Load, and not ExtendedMap::Load.

【讨论】:

如果脚本不提供这样的类,我不希望源有ExtendedMap。这个想法是在我扩展某些(或所有)类之后,在 DLL 本身中重新注册它们【参考方案2】:

这听起来像是“装饰者”设计模式的教科书案例。

【讨论】:

听起来接近我正在寻找的东西,但我如何使核心始终使用脚本提供的装饰器并回退到基类(或它的装饰器)?我希望我的核心始终使用MapDecorator可以在外部 DLL 中定义 我认为您必须对核心代码进行一些重构,以便 Map 对象的所有创建都通过工厂完成,这将公开一些您的脚本挂钩可以用来控制哪些接口创建了装饰地图的味道。我喜欢我在其他答案中看到的一些想法;也许其中一个更适合您的情况。【参考方案3】:

虽然有可能,但非常危险:系统应该对扩展开放(即挂钩),但对更改关闭(即覆盖/重新定义)。像这样继承时,您无法预期客户端代码将显示的行为。正如您在示例中看到的那样,客户端代码必须记住调用超类的方法,它不会:)

一种选择是创建一个非虚拟接口:一个抽象基类,它具有一些调用纯虚函数的模板方法。这些必须由子类定义。

如果您不想创建核心地图,脚本应该为核心提供一个工厂来创建地图后代。

【讨论】:

【参考方案4】:

如果我对类似系统的经验适用于您的情况,则注册了几个挂钩。因此,基于模式 abstract factory 的解决方案不会真正起作用。您的系统接近模式observer,这就是我要使用的。您创建一个基类,将所有可能的钩子作为虚拟成员(如果钩子很多,则创建几个具有相关钩子的基类)。您无需逐个注册钩子,而是注册一个对象,该对象的类型为具有所需覆盖的类的后代。对象可以具有状态,并且可以方便地替换此类回调系统通常具有的void* user data 字段。

【讨论】:

以上是关于用C++定义一个人员类的主要内容,如果未能解决你的问题,请参考以下文章

C++ 抽象类一(多继承与赋值兼容性原则)

selenium 自动化测试个人总结

selenium 自动化测试个人总结

重磅!个人开发人员能够开发上线小程序了

如何使用自定义类一次重置 jquery mobile 中的多个下拉列表

新手用C++写了个泛型堆,效率竟比STL的更快?