Reputation: 39881
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?
Upvotes: 2
Views: 68
Reputation: 179991
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.
Upvotes: 0
Reputation: 91
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);
...
};
Upvotes: 1
Reputation: 22981
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; }
Upvotes: 4