我正在使用UML在c ++中为基本代码建模。 我有初稿。 我想就如何改善它,是否错过了某项内容或图表是否有问题提供反馈。
和代码:
#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 :(得分:1)
可能最好的地方不在这里,而在https://codereview.stackexchange.com/上(仅用于代码)
但是有几句话:
代码和UML建模是一致的,并且可以在没有警告的情况下编译代码,这很好
为什么用A01 : Animal
而不是fred : Animal
,为什么用A02 : Animal
而不是tom : Animal
和D01 : Dog
而不是spot : Dog
?
类图中用于操作参数的符号未遵循UML标准,例如,SetName(string name) : void
必须为SetName(in name : string) : void
或SetName(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.上的照片我很惊讶没有猴子课;-)