如何改善C ++中以下代码的UML建模?

时间:2019-05-16 14:30:40

标签: c++ oop uml

我正在使用UML在c ++中为基本代码建模。 我有初稿。 我想就如何改善它,是否错过了某项内容或图表是否有问题提供反馈。

UML图: structural diagram

和代码:

#include <ctime>
#include <functional>
#include <iostream>
#include <math.h>
#include <numeric>
#include <string>
#include <vector>


// CLASS: declaration -------------------------------------
// # Animal ...............................................
class Animal{
    private:
        std::string name;
        double height;
        double weight;

        // member of a class as static { bit.ly/2EXnDTW }
        static int numOfAnimals;
    public:
        static int GetNumOfAnimals(){return numOfAnimals;}

        void SetName(std::string name){this->name = name;} //<mutator/SETTER
        std::string GetName(){return name;} //<accessor/GETTER

        void SetHeight(double height){this->height = height;}
        double GetHeight(){return height;}

        void SetWeight(double weight){this->weight = weight;}
        double GetWeight(){return weight;}

        //note: possible not to provide a name here with your prototypes
        //ex: void SetAll(std::string, double, double);
        void SetAll(std::string name, double height, double weight);

        Animal(std::string name, double height, double weight); //<constructor
        Animal(); //<overload constructor when no attributes are passed
        ~Animal(); //<deconstructor

        void ToString();
};

int Animal::numOfAnimals = 0;

void Animal::SetAll(std::string name, double height, double weight){
    this->name = name;
    this->height = height;
    this->weight = weight;
}
//constructor
Animal::Animal(std::string name, double height, double weight){
    this->name = name;
    this->height = height;
    this->weight = weight;
    Animal::numOfAnimals++;
}
//overload constructor when no attributes are passed
Animal::Animal(){
    this->name = "";
    this->height = 0;
    this->weight = 0;
    Animal::numOfAnimals++;
}
//destructor
Animal::~Animal(){ std::cout << "Animal " << this -> name << " destroyed\n";}

void Animal::ToString(){
    std::cout << this -> name << " is "
              << this -> height << " cms tall and "
              << this -> weight << " kgs in weight\n";
}

// # Dog ..................................................
class Dog: public Animal{
    private:
        std::string sound = "woof";
    public:
        void MakeSound(){ printf("The dog %s says %s\n", this->GetName().c_str(), this->sound.c_str());}
        Dog(std::string name, double height, double weight, std::string sound);
        Dog(): Animal(){};
        void ToString();
};

Dog::Dog(std::string name, double height, double weight, std::string sound) :
Animal(name, height, weight){
    this->sound = sound;
}

void Dog::ToString(){
    //printf("%s is %d cms tall and %d kgs in weight and says %s\n",
    //        this->GetName().c_str(), this->GetHeight(), this->GetWeight(), this->sound.c_str());
    // note: do not work well with this->GetHeight() and this->GetWeight()
    std::cout << this -> GetName()   << " is "
              << this -> GetHeight() << " cms tall and "
              << this -> GetWeight() << " kgs in weight and says "
              << this -> sound       << "\n";
}

// END CLASS ----------------------------------------------

int main (int argc, char** argv) {
    //create 1st animal - fred
    Animal fred;
    //test overloaded constructor
    fred.ToString();
    //add attributes value of 1st animal - Fred
    fred.SetHeight(33);
    fred.SetWeight(10);
    fred.SetName("Fred");
    fred.ToString();
    //create 2nd animal using constructor - tom
    Animal tom("Tom", 36, 15);
    tom.ToString();
    //create 1st dog - spot
    Dog spot("Spot", 38, 16, "woofWoof");
    //print 2nd dog info
    spot.ToString();
    spot.MakeSound();
    //print number of animal
    std::cout << "Number of Animals : " << Animal::GetNumOfAnimals() << "\n";
    return 0;
}

代码的预期和当前输出:

  • 身高0厘米,体重0公斤
  • 弗雷德身高33厘米,体重10公斤
  • 汤姆高36厘米,体重15公斤
  • 该点高38厘米,重16公斤,说woofWoof
  • 狗点说woofWoof
  • 动物数:3
  • 动物景点被破坏
  • 汤姆被摧毁的动物
  • 弗雷德被摧毁

1 个答案:

答案 0 :(得分:1)

可能最好的地方不在这里,而在https://codereview.stackexchange.com/上(仅用于代码)

但是有几句话:

  • 代码和UML建模是一致的,并且可以在没有警告的情况下编译代码,这很好

  • 为什么用A01 : Animal而不是fred : Animal,为什么用A02 : Animal而不是tom : AnimalD01 : Dog而不是spot : Dog

  • 类图中用于操作参数的符号未遵循UML标准,例如,SetName(string name) : void必须为SetName(in name : string) : voidSetName(name : string) : void(如果隐藏了方向)

  • 我建议您尽可能多地使用 const 操作,例如 getters GetName GetHeight ...)

  • 在没有参数的构造函数中,您不需要做this->name = "";,幸运的是,std::string作为构造函数可以创建一个空字符串

  • Animal::ToString()Dog::ToString()确实不构成字符串,在标准输出上写,它们的名称具有误导性

  • 您声明了析构函数,但未定义它们

  • 因为动物是一个基类,因此将其析构函数 虚拟。万一您从 Animal 指针删除实例实际上是子类的实例,则需要这样做。您错过了递减其中的 numOfAnimals

  • 最好让 ToString virtual 根据实例的实际类型而不是编译时已知的类型来调用版本。在 main 中添加{ Animal * a = &spot; a->ToString(); },然后查看结果。

  • 为什么要在MakeSound()中使用 printf

  • 您允许实例化 Animal ,这是一个可以接受的选择,另一种方法也使该类抽象化而仅允许实例化与有效动物相关的子类

  • 我个人仅使用大写字母来开头为 static 的操作(和属性)名称,以区分它们。

P.S。考虑您在S.O.上的照片我很惊讶没有猴子课;-)