Why should a method be declared in a C ++ class definition?

If you only define this method, it will have a compiler error.

void classA::testMethod() { } 

And so it should be declared first:

 class classA { void testMethod(); }; 

Why should they be announced?

I know that for ordinary C method methods, it does not need to be declared, but you can simply define them:

 void test() { } 
+6
source share
9 answers

There are several secondary reasons, both objective and subjective (i.e., allows you to specify the visibility, serves as an interface for the class and, possibly, several others related to the compilation and linking phases and the visibility of TU characters, not to mention the fact that the class is the main encapsulation unit, with all of this implied), but it is undeniable that the standard dictates this :

N3797 - class.mfct / p2

A member function can be defined (8.4) in a class definition, in which case it is a built-in member function (7.1.2), or it can be defined outside its class definition if it has already been declared but not defined in the class definition. A member function is a definition that appears outside the class definition in the namespace area that spans the class definition. With the exception of the member of the definition of functions that appear outside the class definition, and with the exception of the explicit specializations of member functions of the class, the member function templates and templates (14.7) that appear outside the class definition, the member function should not be updated.

my attention.

+7
source

You do not need to declare a method before defining it, but you need to declare class methods in the class. Otherwise, it will not be a class method.

This may seem like a contradiction, but the definition is also a declaration. So this means that the definition may appear in the class itself:

 class A { void testMethod() { /*...*/ } }; 

[edit] Also, in fact, inside the class declaration there are private , protected and public parts. This is necessary for encapsulation. If you can declare methods outside the class, you will lose encapsulation. Anyone can access private members by simply defining additional getters and setters, even if that doesn't make sense. Class invariants would become meaningless.

+8
source

It helps encapsulation. If you have class A

 class A { public: foo(); bar(); } 

You can be sure that only the foo and bar methods can interact with private members of the class data. (Of course, pointer magic or undefined)

+6
source

All of the previous answers are correct as far as they go, but they do not indicate the reason for this rule. In C ++, the class definition is closed; You cannot add to it later. This is necessary for non-static data members, since they determine the size (and implicitly generated special functions), but this is the basic principle in C ++ for all members of the class: not only data, but functions, types, etc. This is considered essential for good encapsulation.

This is true for most (but not all) languages ​​that support the concept of a class.

This also explains why the situation is different for the namespace (which is not closed).

+3
source

"Methods" or "member functions" (as a more general terminology in C ++) are part of the class declaration. Since you must declare a C ++ class in one place, you must ensure that all "member functions" (or "methods") are already present in this declaration.

I know that the usual methods of method C do not require an declaration, but they can simply be defined

When you refer to the "general method C" in C ++, you actually mean the "general function". Note that you can declare classes wherever you can declare such functions.

Also note that you can declare a member function with a body. You do not need to separate the declaration and definition. That is, this is absolutely true:

 class A{ void privateMethod() { // do something here... } public: void publicMethod() { // do something here... } }; 
+2
source

Note the use of the :: qualifier. It means

  • on the left you have a namespace or class id
  • on the right you have a namespace, class, or method / function identifier

So the void A::testMethod() assumes that there is a class or namespace A - this is how C ++ defines it. And this applies to

 void A::testMethod(); 

and

 void A::testMethod() { } 

Also pay attention to the global namespace, in which you really see nothing to the left of :: , as in

 void ::testMethod() { } 

And by definition, a global namespace is always defined so that the code above defines a C-style-like function without a qualifier.

+2
source

Even if this has not been authorized by the standard, there are two reasons why you need to declare all class methods in the class definition.

  • You can declare something public, private or protected in a class declaration, you cannot do this when defining a method in a .cpp file. So, what would be the visibility of your free-standing class method?

  • If the standard decided to choose one of the three as the default value (the default for C ++ by default), and put this visibility in your method, now you have the problem of defining the scope. Even the most restrictive visibility (private) means that you can use this method in any other member method, including those that are defined before it in the source file. Without an announcement in the class definition, these earlier functions will not know about your free-standing method, so you are violating the rules for defining the scope.

In the foo.h header:

 class foo { public: foo() {} virtual ~foo() {} declaredMethod(); }; 

In your foo.cpp

 foo::declaredMethod() { ... freeStandingMethod(); // This should be legal, but it can't work since we // haven't seen foo::freeStandingMethod() yet ... } foo::freeStandingMethod() { ... } 

Even if you can do this work in the same .cpp file, it is legal to place foo::freeStandingMethod() in another .cpp file from foo::declaredMethod() , after which it becomes impossible.

+2
source

This is not an answer, but you may find it informative and funny. Adding two template functions to your class allows you to name any free function that takes an object of this class as the first parameter:

 #include <string> #include <iostream> struct puppy { puppy(std::string name) : _name(std::move(name)) {} const std::string& name() const noexcept { return _name; } void set_name(std::string name) { _name = std::move(name); } template<class F, class ...Args> auto perform(F&& f, Args&&...args) const -> decltype(f(*this, std::forward<Args>(args)...)) { return f(*this, std::forward<Args>(args)...); } template<class F, class ...Args> auto perform(F&& f, Args&&...args) -> decltype(f(*this, std::forward<Args>(args)...)) { return f(*this, std::forward<Args>(args)...); } private: std::string _name; }; void woof(const puppy& p) { std::cout << "puppy " << p.name() << " woofs!" << std::endl; } void indented_woof(const puppy&p, size_t indent) { std::cout << std::string(indent, ' '); woof(p); } void complex_woof(const puppy& p, int woofs) { std::cout << "attention!" << std::endl; for (int i = 0 ; i < woofs ; ++i) { p.perform(indented_woof, 4); } } std::string name_change(puppy& p, std::string(new_name)) { auto old_name = p.name(); p.set_name(std::move(new_name)); return old_name; } int main() { puppy fido { "fido" }; fido.perform(woof); fido.perform(complex_woof, 10); auto old_name = fido.perform(name_change, "bonzo"); fido.perform(woof); std::cout << "changed name from " << old_name << std::endl; return 0; } 
+2
source

why should declare these? I know for common c method, there is no need to declare, instead of it just define it:

In C there is no method, but only an attribute of the structure, which can be a Pointeur function, and then associated with the address of the function.

In addition, you must declare it in the class definition for the same reason as you, in C:

The compiler will change this preliminary declaration into a pointer function, and then associate this method with the construction of your object.

If a C ++ class definition needs to be converted to a C structure, the code will look like this:

 struct Aclass { void (*Amethode))(int); } void Amethode(int) { return (0); } Aclass primaryObject = {&Amethode}; Aclass* AclassConstructor() { Aclass* object; object = malloc(sizeof(Aclass)); memcpy(object, primaryObject, sizeof(Aclass)); return (object); } 
+1
source

Source: https://habr.com/ru/post/975874/


All Articles