Recently, a magic compile error occurred while using the namespace and the youyuan function. After thinking, the problem was finally solved. I hope it will be helpful to you.
Let's talk about namespaces first. When writing a C Project, especially a program with more than 10 million lines, namespace conflicts are a very crashing thing. Currently, the most widely used solution is to make the function name very long and learn about GTK ). In C ++, a feature called "namespace" is added, which is declared, defined, and used by the keyword "namespace. I believe that students who have studied C ++ have a deep understanding of how to use the namespace. I will not introduce it here.
When we sometimes need to overload some operators of the class, it is difficult to avoid the use of the "friend function ". Once upon a time, Daniel criticized the encapsulation of the "youyuan function" damage class. However, for low-level coder like me, the "Friends function" does bring a lot of convenience.
Question 1:
Let's look at a simple code:
- class istream;
- istream& operator>>(istream&,int&);
- class CA
- {
- int a;
- friend istream& operator>>(istream&,CA& );
- };
- istream& operator>>(istream& is,CA& a)
- {
- is>>a.a;
- return is;
- }
- int main()
- {
- extern istream stream;
- elephant::CA a;
- stream>>a;
- }
Save as a. cpp and compile it without link ).
Because there is no definition of the istream class, the link will certainly fail. Use the-c option to compile without link.
At this time, there is no problem with compilation.
When I want to include the CA class in an elephant command space, a problem occurs. Use code to speak:
- class istream;
- istream& operator>>(istream&,int&);
- namespace elephant
- {
- class CA
- {
- int a;
- friend istream& operator>>(istream&,CA& );
- };
- }
- istream& operator>>(istream& is,elephant::CA& a)
- {
- is>>a.a;
- return is;
- }
- int main()
- {
- extern istream stream;
- elephant::CA a;
- stream>>a;
- }
Similarly, only compilation, no link, and an error is reported:
# G ++-c a. cpp A. cpp: In function 'istream & operator> (istream &, elephant: CA &)': A. cpp: 7: error: 'int elephant: CA: a' is private A. cpp: 13: error: within this context |
What do you mean? A is a private member and cannot be accessed. I made you friend. You told me you couldn't access it. Why?
Let's try to modify the code and add operator> function to the elephant namespace, that is, change row 11th:
- istream& elephant::operator>>(istream& is,elephant::CA& a)
Compile only, do not link, report error:
# G ++-c a. cpp A. cpp: 11: error: 'istream & elephant: operator >>>( istream &, elephant: CA &) 'Could have been declared inside 'elephant' |
It said that this function should be declare in the elephant namespace. I believe you can distinguish the difference between declare and define. The first one is "Declaration", and the other one is "Definition "). Then we will declare. The complete code is as follows:
- class istream;
- istream& operator>>(istream&,int&);
- namespace elephant
- {
- class CA
- {
- int a;
- friend istream& operator>>(istream&,CA& );
- };
- istream& operator>>(istream&,CA&);
- }
- istream& elephant::operator>>(istream& is,elephant::CA& a)
- {
- is>>a.a;
- return is;
- }
- int main()
- {
- extern istream stream;
- elephant::CA a;
- stream>>a;
- }
Compile only, not link. Compiled successfully.
Summary:
1. friend does not declare the function, so we need to declare this function separately. Friend only tells this class that this function has access permissions to Private Members of this class.
2. The declared functions in the namespace have been included in the namespace. The namespace specifier should be used for definition.
3. friend only shows that the elephant: operator> function is a CA-like membership function, while the operator> function is not a membership function like CA. Therefore, the compiler reports an error if operator> operator class CA is a private member.
4. elephant: operator> and operator> are not a function. The former is a function defined in the elephant namespace, while the latter is a global function.
Question 2:
Or a simple code:
- void output(int a);
- class SA
- {
- int data;
- friend void output(const SA&);
- };
- void output(const SA& a)
- {
- output(a.data);
- }
- int main()
- {
- SA a;
- output(a);
- }
Compile only, not link. No problem. Now, similarly, I want to put the class SA in the elephant namespace. According to question 1, we also need to put the output function in the elephant namespace. The Code is as follows:
- namespace elephant
- {
- class SA
- {
- int data;
- friend void output(const SA&);
- };
- void output(int a);
- void output(const SA&);
- }
- void elephant::output(const elephant::SA& a)
- {
- output(a.data);
- }
- int main()
- {
- elephant::SA a;
- elephant::output(a);
- }
Compile only, not link. No problem.
However, due to some special needs, I want the output function and all its overload functions to be defined in the global space. What should I do?
I tried it twice. The first attempt failed. The code above:
- void output(int a);
- namespace elephant
- {
- class SA;
- }
- void output(const elephant::SA&);
- namespace elephant
- {
- class SA
- {
- int data;
- friend void output(const SA&);
- };
- }
- void output(const elephant::SA& a)
- {
- output(a.data);
- }
- int main()
- {
- elephant::SA a;
- output(a);
- }
Because the output function requires elephant: SA type parameters, a forward declaration is made for elephant: SA. However, obviously, this is not acceptable. According to question 1, elephant: output has access permissions to the private members of elephant: SA, but output does not.
How can this problem be solved? Or, how to declare the output function of the global space as the friend function of elephant: SA. A: Use the global space specifier. Code:
- void output(int a);
- namespace elephant
- {
- class SA;
- }
- void output(const elephant::SA&);
- namespace elephant
- {
- class SA
- {
- int data;
- friend void ::output(const SA&);
- };
- }
- void output(const elephant::SA& a)
- {
- output(a.data);
- }
- int main()
- {
- elephant::SA a;
- output(a);
- }
Compile only, not link. Successful.
":" Is preceded by a space, which is called a global space descriptor. I believe you have learned C ++ before. I will not explain it in detail here.
Summary:
1. When you define a class membership function in a namespace, It defaults to a function in the same namespace.
2. If you want to point to a function in the global space, use the global space specifier.
Related information:
Operating System: ubuntu linux 10.10 maverick
Compiler: g ++ version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5)
This article is from the "elephant_liu" blog, please be sure to keep this source http://elephantliu.blog.51cto.com/1107116/610844