Declare, then define a class method - Why an error? - c++

Why doesn't this compile?
class Test
{
void foo();
void foo()
{ }
};
But these will compile:
void bar();
void bar()
{ }
// In same header/file
class Test
{
void foo();
};
void Test::foo()
{ }
The compiler would say that given method cannot be overloaded. The method Test::foo is not being overloaded - it is the same function with exact same signature.

It's explicitly prohibited by the C++ standard. Right there at [class.mfct/1]
A member function may be defined in its class definition, in which
case it is an inline member function, or it may be defined outside of
its class definition if it has already been declared but not defined
in its class definition. A member function definition that appears
outside of the class definition shall appear in a namespace scope
enclosing the class definition. Except for member function definitions
that appear outside of a class definition, and except for explicit
specializations of member functions of class templates and member
function templates ([temp.spec]) appearing outside of the class
definition, a member function shall not be redeclared.

It is just the way it is in C++. Redeclaring a class member is not allowed (unless you consider an out-of-class definition as another declaration). Redeclaring a namespace member is OK as long as you obey ODR.

Why doesn't this compile?
class Test {
void foo();
void foo() { }; // wrong
};
Because, as StoryTeller and others answered, you are declaring and defining the same member function void Test::foo(void) twice (and the inside-class definition of foo is implicitly inline).
If you want to define a member function in your header file after the class, you'll better declare it explicitly as inline like this:
class Test {
inline void foo();
};
and later define that member function (e.g. below in the same header file):
void Test::foo() {
// body of Test::foo
}
BTW, if you declare a member function with outside definition like above, and that member function is not inline but is defined in some header file which is included in several translation units, that function would be multiply defined and the linker would complain.

void foo();
and
void foo() {}
are two ways of declaring functions in a class definition. The first only declares the function and the second declares the function and also implements it. Therefore the compiler assumes that you are going to re-declare the same function and is not a correct overload as the function signature is the same in both.

Related

C++ class prototype not working properly?

I'm trying to create a class prototype, however I keep getting the error: 'aClass' uses undefined class 'myClass'
I'm pretty sure I'm making the prototype properly. Using a prototype function works, however class prototype doesn't.
extern class myClass; // prototypes
extern void myFunction();
int main() // main
{
myClass aClass;
myFunction();
return 0;
}
class myClass { // this doesn't work
public:
void doSomething() {
return;
}
myClass() {};
};
void myFunction() { // this works
return;
}
myClass aClass; is a definition, which requires myClass to be a complete type; the size and layout of myClass must be known at that point, at compile-time.
Any of the following contexts requires class T to be complete:
...
definition of an object of type T;
...
That means the class has to be defined before that.
Note that forward declaration works for those cases that don't require the type to be complete, e.g. a definition of pointer to the type (like myClass* p;).
For functions the story is different. A function is odr-used if a function call to it is made, then its definition must exist somewhere. Note that the definition is not required at compile-time, defining it after main() (with declaration before) is fine.
a function is odr-used if a function call to it is made or its address is taken. If an object or a function is odr-used, its definition must exist somewhere in the program; a violation of that is a link-time error.
BTW: Using extern in forward declaration of a class is superfluous.

Can the scope resolution operator be used in the definition of a member function when the member function is defined outside of its class definition?

Can the scope resolution operator be used in the definition of a member function when the member function is defined outside of its class definition? Like this:
class Myclass{
private:
void foo();
public:
void foo2();
};
void Myclass::foo()
{
// do stuff. . .
}
My teacher gave us notes that demonstrate the use of the scope resolution operator only for member functions that are public. Can anyone clear this up?

How are inline members of classes compiled?

I am new to c++ (and to programming itself) and this is what I heard:
If we compile an ordinary function, The compiler creates a pointer to that function and place the instructions that make up the body of the function elsewhere. This is how an ordinary function gets compiled. But in case of inline functions, the compiler generates code during compilation and replaces it with the inline function call.
My question is when member functions (of a C++ class) are compiled, are they treated as inline functions or are they treated as ordinary functions?
They are just like normal functions, with one exception: if you write the function definition inside the class definition (example below), then the function is automatically given the inline keyword:
[C++11: 9.3/2]: A member function may be defined (8.4) in its class definition, in which case it is an inline member function (7.1.2), or it may be defined outside of its class definition if it has already been declared but not defined in its class definition.
struct T
{
void foo() // the same as `inline void foo()`
{
// ...
}
};
That doesn't automatically mean the class will be inlined, though; the inline keyword is just a hint and is largely ignored nowadays when it comes to deciding whether to actually inline a function, though it does assuredly affect linkage.
You asked:
are they treated as inline functions or are they treated as ordinary functions?
Member functions of classes can be inline or non-inline depending on how they are declared and defined.
Here's the relevant info from the standard:
9.3 Member functions
2 A member function may be defined (8.4) in its class definition, in which case it is an inline member function (7.1.2), or it may be defined outside of its class definition if it has already been declared but not defined in its class definition. A member function definition that appears outside of the class definition shall appear in a namespace scope enclosing the class definition...
Example:
class A
{
A() : data(0) {} // Inline function
inline A(A const& copy) : data(copy.data) {}
// Inline function. The keyword inline
// can be used but not necessary.
int data;
};
3 An inline member function (whether static or non-static) may also be defined outside of its class definition provided either its declaration in the class definition or its definition outside of the class definition declares the function as inline. [ Note: Member functions of a class in namespace scope have external linkage. Member functions of a local class (9.8) have no linkage. See 3.5. —end note ]
Example:
class A
{
A(); // Declaration doesn't say whether the function is inline or not.
inline A(A const& copy); // Declaration says the function is inline.
int data;
};
inline A::A() : data(0) {} // Implementation says the function is inline.
inline A(A const& copy) : data(copy.data) {}
4 There shall be at most one definition of a non-inline member function in a program; no diagnostic is required. There may be more than one inline member function definition in a program. See 3.2 and 7.1.2.
Example:
class A
{
A(); // Declaration doesn't say whether the function is inline or not.
inline A(A const& copy); // Declaration says the function is inline.
int data;
};
inline A(A const& copy) : data(copy.data) {}
// Must be defined in a .h file since the declaration says the function is inline.
A::A() : data(0) {} // Non-inline implementation.
// It must be defined in only one translation unit (a .cpp file, not a .h file).
Whether to inline a function or not is entirely up to the compiler's discretion, which means that different compilers might have different criteria for function inlining. That being said, you can prompt the compiler to inline a function with keywords such as inline, __inline, and __forceinline. Still, it does not guarantee that your function will be inlined.
However, there are cases where it's generally impossible to inline. This link from Microsoft would probably give you a good idea about function inlining.
An example of a function that cannot be inlined will be a virtual function. As virtual function calls(i.e. which virtual function definition to call) are determined on run-time, it is impossible for the compiler to figure out which exact function definition will be called at each call of the virtual function.
#include <iostream>
class Base
{
public:
virtual int VirtualFunc();
};
class Derived1 : public Base
{
public:
virtual int VirtualFunc() { return 1; }
};
class Derived2 : public Base
{
public:
virtual int VirtualFunc() { return 2; }
};
int main(void)
{
Base* pBase;
size_t choice;
std::cin >> choice; //Get user input
if(choice == 1) //If user inputs 1, create a Derived1
pBase = new Derived1;
else if(choice == 2) //If user inputs 2, create a Derived2
pBase = new Derived2;
pBase->VirtualFunc(); //At compile-time, no idea if pBase will be Derived1 or Derived2
return 0;
}
Thank you for reading.
Compilation of class methods works same as standalone functions. If you put inline keyword before it, compiler will try to insert it's code to place, where it is called, if it's possible.

Friend function declaration/definition inside a namespace

Consider a class inside a namespace. The definition of the class declares a friend function.
namespace Foo
{
class Bar
{
friend void baz();
};
}
This should, based on what I know, declare baz() as a member of the innermost enclosing namespace, i.e. Foo.
Therefore, I expected the following definition for baz() to be correct:
void Foo::baz() { }
However, GCC (4.7) gives me an error.
error: ‘void Foo::baz()’ should have been declared inside ‘Foo’
Several solutions seem to work:
Declare baz() outside the class.
namespace Foo
{
void baz();
class Bar
{
friend void baz();
};
}
Define baz() inside the namespace.
namespace Foo
{
class Bar
{
friend void baz();
};
}
...
namespace Foo
{
void baz() { }
}
Compile with the -ffriend-injection flag, which eliminates the error.
These solutions seem to be inconsistent with the general rules of declaration/definition in C++ I know.
Why do I have to declare baz() twice?
Why is the definition otherwise only legal inside a namespace, and illegal with the scope resolution operator?
Why does the flag eliminate the error?
Why do I have to declare baz() twice?
Because the friend declaration doesn't provide a usable declaration of the function in the namespace. It declares that, if that function is declared in that namespace, it will be a friend; and if you were to define a friend function inside a class, then it would be available via argument-dependent lookup (but not otherwise) as if it were declared in the namespace.
Why is the definition otherwise only legal inside a namespace, and illegal with the scope resolution operator?
Because it hasn't been (properly) declared in the namespace, and a function can only be defined outside its namespace (with scope resolution) if it has been declared.
Why does the flag eliminate the error?
Because the flag causes the friend declaration to act as a declaration in the namespace. This is for compatibility with ancient dialects of C++ (and, apparently, some modern compilers) in which this was the standard behaviour.
The first piece of code should compile:
namespace A {
struct B {
friend void foo();
};
}
void A::foo() {}
Although it that particular function cannot be used unless you also provide a declaration at namespace level. The reason is that friend declarations are only seen through Argument Dependent Lookup (ADL), but foo does not depend on A::B, and thus the compiler will never look inside that type.

Is a friend function defined in-class automatically inline?

If a member function is defined inside the class, it is an inline function. E.g.
struct X
{
void mem_f() {} //mem_f is inline
};
My question is whether a nonmember friend function defined inside the class is also automatically inline.
E.g.
struct Y
{
friend void friend_f() {} //is friend_f inline?
};
A relevant quote/paragraph_no from the standard would be much welcome. Thanks.
Yes, it is. §11.4/5:
A function can be defined in a friend
declaration of a class if and only if
the class is a non-local class (9.8),
the function name is unqualified, and
the function has namespace scope.
Such a function is implicitly inline. A friend function defined in
a class is in the (lexical) scope of
the class in which it is defined. A
friend function defined outside the
class is not (3.4.1).
Since the class definition is presumably in a header file, the function will be multiply-defined, so it needs to be inline.