I am reading TCPPPL by Bjarne Stroustrup and I came across the following piece of code (shown below). I have two questions:
Where is the body of the function operator+? I mean there is only the declaration of the function in class X.
What does the line X(int) mean? Is this the constructor with int as a parameter or something else?
class X {
public:
void operator+(int);
X(int);
};
void operator+(X,X);
void operator+(X,double);
void f(X a)
{
a+1; // a.operator+(1)
1+a; // ::operator+(X(1),a)
a+1.0; // ::operator+(a,1.0)
}
1) Where is the body of the function operator+? I mean there is only the declaration of the function in class X.
The definition (body) of operator+ can be anywhere. The code is obviously not a complete program (there is no main). Therefore, the definitions might be below the shown code or even in another compilation unit.
2) What does the line X(int) mean? Is this the constructor with int as a parameter or something else?
This is a declaration of a converting constructor of class X that accepts an integer as an argument.
What does the line X(int) mean?
X(int) is a declaration of a constructor accepting a single integer parameter. Definition is missing.
Where is the body of the function operator+
Wherever you defined it.
This code won't work without the correct definitions.
Related
Accidentally I compiled a source similar to this:
//void y(); //optionally declaring y()
void x()
{
//some code...
void y();
//some code...
}
//void y() {/*some code*/} //optionally defining y()
This was compiled with VS 2017 and also two clang versions. None of these compilers complained about this source code – no errors, no warnings. There was a typo in my code – in this example, there should be no void in front of y() and therefore y() was supposed to be called, so it was a rather sneaky bug with no visible consequences while compiling.
I was curious what the compiler was thinking. Trying to debug the code, the void y(); line inside x() was inaccessible, so seems like no actual machine code was produced. I tested this with the void y() {/*somecode*/} function declared above and defined below x() and also with no such function – no difference.
Did the compilers consider this a declaration? if so, how this could be further used when defining a function within a function this way (not speaking about lambdas) is not allowed in C++? I assume that if such a declaration is valid inside a function, it would mostly make sense if one wanted to define a function inside x() as well, otherwise the declaration of y() could be moved outside and above x().
EDIT: Related discussions and explanations:
Function declaration inside of function — why?
Syntactic ambiguity — most vexing parse
I was curious what the compiler was thinking.
Its thinking that you declared a function by the name y that returns void and has an empty argument list. void y(); is a function declaration.
Did the compiler(s) consider this a declaration?
Yes.
if so, how this could be further used when nested functions are not allowed in C++?
You can use a function declaration for example to call it, or to take its address. Like so:
void x()
{
void y(); // a function declaration
// now that y has been declared, it can be called:
y(); // a function call
// also, it is now possible to take the address:
void (*fun_ptr)() = y;
}
When I create a function, I can put the code for it after main if I put the prototype above main. For example,
int myFunction(int a)
{
return(a);
}
would have the prototype..
int myFunction(int a);
above main.
However, I have not been able to get this to work for a class definition.
If I put …
class myClass
{
…
};
below main,
I get an error if I put
class myClass;
above main. The error occurs where the class is used within main, and the error is "unknown type name." That's with the c++ compiler that is part of Xcode.
What kind of prototype should I enter above main if the class definition is below main?
When you call a function and the definition is not available, the compiler doesn't have to know the contents in order to continue evaluating the rest of the code (eg: stack usage at the call site). It only needs to know the function's signature to ensure the correct parameters are going to be passed into the function. The linker will hook up the actual address for the function call after the compiler is done.
However when you are using a class it has to know about the details of it - not just that it exists - because it'll need to ensure proper layout on the stack, what parameters are required for the constructor, etc.
The details of the class' functions are of course like regular functions - it just needs the signature to work with - they can be defined later.
A function in C++ is like a black box to its callers; they just need to know what to pass it and what it returns in order to use it.
Classes, on the other hand, cannot be used in this way, because the compiler needs to know how much space to allocate for them, what the types of their members are, etc.
A class definition is a little different because it can contain member function prototypes and definitions.
If your class definition (usually placed in a .h file) is in the same file, then you'll want it to be above your main(). Functions defined outside of your class definition can be defined after main() as shown below.
class Foo
{
// member function prototype
void func1();
//member function definition inside class
void func2()
{
std::cout << "Hello from func2" << std::endl;
}
};
int main()
{
foo instance;
instance.func1();
instance.func2();
return 1;
}
void Foo::func1()
{
std::cout << "Hello from func1" << std::endl;
}
In a way, a function prototype is the function-equivalent of a complete class definition, not a forward declaration.
so, forward declaration:
class X;
introduces the name X and informs the compiler that it is a class. After seeing this, the compiler will allow you to hold and transfer references and pointers to an X, but not create or copy values (instances) of it, so:
void foo(X&); // is allowed (because it deals in references), but
void foo(X); // is not (it deals in copies of an X)
class definition:
class X { ... };
fully defines X's interface and storage requirements. After this, the compiler will allow you to do anything you like with an X. This is why the class definition generally goes into a header file.
function prototype involving forward-declared classes:
int foo(X&); // X may be forward-declared or defined
This has fully declared the complete shape and behaviour of calling foo(X&). The code at the call-site can be completely compiled.
function prototype involving defined classes:
int foo2(X); // X must be defined
This has fully declared the complete shape and behaviour of calling foo2(X), including the requirements for copying the X onto the stack (for emplacing it there when called with a temporary). The code at the call-site can be completely compiled.
I always thought that if I declare member of a class inside class this member is known at the entire scope of a class that is:
class X
{
public:
X(int a) :v_(a)
{}
private:
int v_;//even though v_ is declared here I'm using it in ctor which is above this line
};
So that makes sense to me.
Anyhow this doesn't because I'm getting error that v_ isn't known
class X
{
public:
X(decltype(v_) a) :v_(a)//error on this line, compiler doesn't know v_
{}
private:
int v_;
};
Would be glad to learn why.
I'm using intel compiler v14 SP1
Thank you.
3.3.7 Class scope
1 The following rules describe the scope of names declared in classes.
1) The potential scope of a name declared in a class consists not only of the declarative region following
the name’s point of declaration, but also of all function bodies, brace-or-equal-initializers of non-static
data members, and default arguments in that class (including such things in nested classes).
...
That means that you can use v_ in function bodies, constructor initializer lists and default arguments. You are not allowed to use v_ in parameter declarations the way you used it in your code.
For example, this shall compile
class X
{
public:
X(int a = decltype(v_)()) : v_(a)
{}
private:
int v_;
};
but not the second example in your original post.
Your code compiles with Clang.
Reading C++11 specifications you are not allowed to declare the variable after it is being used as function/constructor parameter.
In many cases classes including function signatures will be defined in headers, but function bodies in cpp files. Since the header will have been read by the compiler at the start of reading the cpp file, this problem does usually not occur. But indeed, C++ compilers don't look ahead.
In the code below, why does the compiler not complain for mClass2?
class CMyClass{
private:
CMyClass(){}
};
void TestMethod(){
CMyClass mClass1; //Fails.
CMyClass mClass2(); //Works.
}
Because you've just declared a function mClass2 of zero arguments that returns a CMyClass. That's a valid option since there could be, say, a static CMyClass instance which that function has access to. Note that CMyClass still has a public copy constructor.
(To convince yourself, compile this module to assembler and observe that commenting out the line CMyClass mClass2(); produces the same output.)
Because it is declaring a function and not calling the constructor as you think.
This is called as the Most Vexing Parse in c++.
CMyClass mClass2();
declares a function mClass2() which takes no parameter and returns CMyClass
The second one is a function declaration.
People ought to move to the uniform syntax initialization in C++0x/C++11 using the {} brackets instead which removes this issue.
Class C{};
http://www2.research.att.com/~bs/C++0xFAQ.html#uniform-init
What does it means when I in my code declare something like :
Foo * foo();
What benefits it gives me ?
Ist not simple pointer variable as you see .
Also
What does it mean if I declare it in the c++ source above all methods for example :
// Test cpp class
.
#include "Foo.h"
Foo * foo();
Test::Test() {}
Test::GetFooMethods()
{
foo()->someMethod();
}
…
…
Foo * foo(); is a declaration to a function named foo which returns a pointer to a Foo object. It is not a function pointer.
The code Foo()->someMethod(); is probably a typo. You probably meant foo()->someMethod();. In this case, the code calls foo() which as stated above returns a pointer to a Foo object, and then you call the Foo::someMethod() method through that pointer.
If in fact you did mean Foo()->someMethod(); things get a little crazy. What this means is first a Foo object is default initialized on the stack. Then Foo::operator->() is called, returning some object which has a method named someMethod(), and that function is called. See why I guess that it was a typo? :)
EDIT:
To answer the last question in your post, when you declare a function without defining it, you are telling the compiler, "I've got a function named foo that takes no parameters and returns a pointer to a Foo, but I'm not going to tell you how that function is implemented yet." This allows you to write code that uses that function and the compiler will be happy. The linker however will be quite grumpy with you if you do not someplace provide a definition for this function.
Foo * foo();
This is not a function pointer. This is a declaration of a function named foo that takes no arguments and returns a pointer to a Foo.
A pointer to a function of this type would look like:
Foo* (*foo_ptr)() = foo;
Just like
int getX();
is a declaration of a function that returns an int, so too
Foo * foo();
is a declaration of a function that returns a Foo pointer;
What does it means when I in my code
declare something like : Foo * foo();
Foo * foo();
Very tough to say without knowing what is Foo.
If Foo is a type e.g. struct Foo{};, then this declares a function named 'foo' which returns a pointer to some type called Foo. This looks to be the case in your post based on your usage subsequently (and also the title of the post).
If Foo is a #define e.g. #define Foo 1, then this is not a declaration but an expression statement which multiplies 1 by the return value of 'foo' in case operator * is defined for the types of the operands involved.
What benefits it gives me ?
Tough to say again without knowing what Foo is.
Also What does it mean if I declare it
in the c++ source above all methods
Declaring 'foo' (if it is indeed a declaration) as high as possible in the translation unit means larger the tentative scope of the name 'foo'.
void f1(){g();} // not OK, 'g' not known
void f(){}
void g(){f();} // OK, f() is known
BTW, does Foo (caps F) have an overloaded operator ->?