简体   繁体   中英

Inheritance and small number of parameters

Uncle Bob in his Clean Code suggests that no more than 3 arguments should a function get:

Functions that take three arguments are significantly harder to understand than dyads. The issues of ordering, pausing, and ignoring are more than doubled. I suggest you think very carefully before creating a triad.

But what about CTOR arguments in class inheritance hierarchy? What if each class in hierarchy adds a new field and you should initialize them in CTOR. See an example below:

class Person
{
private:
    std::string m_name;
    int m_age;

public:
    Person(const std::string& name, const int age);
    std::string getName() const { return m_name; }
    int getAge() const { return m_age; }
    ~Person();
};


class Student : public Person
{
private:
    std::string m_university;
    int m_grade;

public:
    Student(const std::string& name, const int age, const std::string& university, const int grade);
    std::string getUniversity() const { return m_university; }
    int getGrade() const { return m_grade; }
    ~Student();
};

See how Student gets 4 arguments, while Person gets only 2 and Student adds two more. So how we should handle this?

There are several ways.

Combine multiple parameters into a struct

struct PersonInfo {
    std::string name;
    int age;
};

struct StudentInfo {
    PersonInfo person_info;
    std::string university;
    int grade;
};

Person::Person(const PersonInfo &info) :m_name(info.name), m_age(info.age) {}
Student::Student(const StudentInfo &info) : Person(info.person_info), m_university(info.university), m_grade(info.grade) {}

Default initialize data members and set them with setter utilities

Person::Person() : m_age(0) {}
void Person::set_age(int age) { m_age = age; }

Student() : m_grade(0) {} // Person is default constructed.
void Student::set_grade(int grade) { m_grade = grade; }

i'd say this was just a suggestion. it's fully up to you - how many arguments should your functions get.

but if you prefer to follow the rule, make some sort of parameters holder, like:

class Student
{
  public:
    struct StudentParameters
    {
      ...
    };
    Student(name, age, const StudentParameters &sp);
...
};

You're confusing two distinct meanings of the word function .

The first meaning is more related to the original mathematical meaning of the word. In this case, function is a named relation between one or more inputs and exactly one output. The "Clean Code" rules refers to this meaning, and tells you that more should be limited to 3 inputs.

The alternative meaning in C++ refers to a block of code, which may or may have inputs, which may or may have an output, which may or may have a name.

And yes, even in the latter sense, constructors are unusual functions. They never have a return type, not even void , and they don't have names. So you can rationalize that they're also special when it comes to their number of input arguments.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM