Why having function in my class doesn't change size of this class? This info must be stored somewhere, but where?
You can think of a member function as being just like any other function, except that it has an extra, hidden parameter that takes a pointer to the instance on which the member function was called.
For example, this:
class C
{
void f(int i) { }
};
might be implemented (at least conceptually) as:
void C_f(C* this, int i) { }
If it was a const member function, then the hidden parameter would have the type const C* instead. Note that the situation isn't nearly this simple for virtual member functions.
The sizeof(TheClass) is affected only by the data members within the class, plus the vtable if there is any, plus padding bytes if there is any. So adding a nonvirtual function to your class does not affect its size. And if the class already contains a virtual function, adding a second one would not change sizeof(TheClass) either.
Me think (and I tend to be wrong most of the time) that if you only declare a non-virtual function in a class but no implementation the linker will probably remove it all together.
class Toto
{
int foo();
};
M.
Related
Suppose we wan't to hint the compiler to inline member function where applicable.
class Base
{
public:
inline virtual f() = 0;
};
class Derived : public Base
{
public:
virtual f() override; // no inline specifier here
};
Do I need to specify inline in Derived::f() or can I omit the keyword and be sure that virtual Derived::f() is the same thing as inline Derived::f() ?
I mean is the inline keyword implicitly specified for Derived::f() or do I need to explicitly type it once again?
Do I need to specify inline in Derived::f() or can I omit the keyword and be sure that virtual Derived::f() is the same thing as inline Derived::f() ?
If you omit the inline keyword in the derived class, it is not inline in the derived class.
I mean is the inline keyword implicitly specified for Derived::f()
No, it is not.
or do I need to explicitly type it once again?
Yes, you do. However, a compiler will most likely generate code for it as though it is a non-inline member function since it is a virtual member function.
What does the inline keyword do?
Modern compilers try to balance the costs of inlining a function with the benefits.
Both the benefits and the costs are pretty clear: When a function gets inlined, there's no overhead to the function call (since there is no function call), and the compiler is able to do optimizations to the body of the function based on the context within which it's being called (since, when it's inlined, it knows that context).
Costs may include increased executable size (if it's a big function), and more instances of the assembly for the body of the function being plastered around the executable.
A rule of thumb is that if a function is big or complex, it probably won't be inlined. If it's small, it probably will be inlined.
This is good. It prevents bloated executables, but still eliminates nearly all the overhead associated with using functions. The time to execute a big, complex function oftentimes dwarfs the cost of the function call, and inlining it would have only minimal benefit.
So what does inline do? The compiler calculates how complex a function is when deciding to inline it. It then compares that calculation to some threshold. If the function is less complex than the threshold, it inlines the function.
The inline keyword basically raises the threshold for that particular function, but what it actually does under the hood varies from compiler to compiler.
Can all function calls be inlined?
If the compiler doesn't know what function is getting called, it can't inline it.
Let's look at an example:
// func_t is a pointer to a function that returns an integer
using func_t = int(*)();
int getNumber(func_t func) {
// The compiler can't inline func(), because it doesn't know
// what func *is*
return func();
}
How does this apply to virtual functions?
A virtual function call is pretty similar to invoking a function pointer, but with a few key differences. If you're invoking it from the base class, the compiler doesn't know ahead of time what function to invoke:
class Base {
virtual int getNum() { return 0; }
};
class Derived {
int value;
void setValue(int v) { value = v; }
int getNum() override { return value; }
};
int getNumFrom(Base& base) {
// The compiler doesn't know whether to call
// Base::getNum() or Derived::getNum(), so it can't inline it
return base.getNum();
}
However, if you're invoking it from a concrete instance of a class (not a reference, and not a pointer, the compiler knows exactly which version is getting called:
int getNumFromDerived() {
Derived d;
// Here, we know that we're calling Derived::getNum()
// so the compiler *can* inline it.
return d.getNum();
}
How should you apply the inline keyword?
You can specify it both in the base class, and in the derived class. Just know that it won't guarantee they get inlined, precisely because sometimes it's impossible to inline a virtual function call.
Are there alternatives?
Because templates preserve type information, the compiler always knows which function to call. It's easy to inline templated function calls, and using them won't add overhead to your program.
If possible, prefer templates over virtual inheritance.
I am making a class which is inherited from std::fstream. I am making a custom eof() function. That function returns the value of a bool internal_eof variable which is set and reset under slightly different conditions than those of the std::fstream::eof(). These conditions are specific to the nature of my application. The value of bool internal_eof is determined by other functions which are not shown here. Since the BufferedFile::eof() function which I'm defining just consists of a single statement to return the bool internal_eof varaible, I've decided to make it an inline function. I'm wondering, can an inline function of the derived class override a noninline function of the base class? What does the standard say? What do you more experienced programmers know anything about this? I don't really have time for testing this manually, because the fstream::eof() and BufferedFile::eof() behave similarly ~85% of the time. There are just some edge cases where this solution is needed, and they are not easy to reproduce. Knowing whether this solution is a viable one is crucial for further development of the project.
class BufferedFile: public fstream {
public:
inline bool eof() const { return internal_eof; }
...
private:
bool internal_eof;
...
};
The original intent of the inline keyword was a hint for the optimizer that a function/method is preferred to be a candidate for inline substitution. However, compilers are free to use inline substitution for any function, even though it's not marked as inline.
In modern compilers, inline is of less use for optimization, but for informing the compiler that a function (and variable, since C++17) definition may occur in several translation units and it should consider them as the same definition. (See inline specifier)
Whichever it is, the inline keyword is a specifier used by the compiler and is not actually part of a method's signature, and virtual methods can be overridden in derived classes as long as their signature is not changed, whether declared as inline or not.
Except main() (It is compiled and executed at run-time, so you can't compile it at compile-time), all valid C++ functions are overridable:
class Base
{
public:
virtual ~Base(); // Virtual destructor...
virtual void example(); // Function is already 'inline' here... So, it is one of the
// cases where the 'inline' specifier is redundant...
// and similar was found in your class...
};
Here, inline is a specifier, like virtual, and is not a type (nor does it give the function the power to become unique), so overriding it is not a problem...
class Derived : Base
{
public:
virtual ~Derived(); // Virtual destructor...
void example() override;
};
See inline to know more about this specifier...
I need to forward-declare a class in my header file, like this:
class MyStaticClass;
I understand why one cannot forward-declare data members of this class. I used to think that you could however forward-declare functions. I would like to declare a static function of this class, like this:
class MyStaticClass;
static int MyStaticClass::AddTwoNumbers(const int a, const int b);
This gives me a compile error though:
error C2027: use of undefined type 'MyStaticClass'
Why can this not be done? Or is there a secret way of doing this after all?
This is not allowed because it would allow others to add member functions to a class without even editing the class itself.
Consider this,
struct X
{
static void f(float a) { std::cout << a << std::endl; }
private:
static int _data; //inaccessible to non-member
};
X::f(0); //convert 0 (an int) to float, and call X::f().
Now imagine someone came and forward-declare the following function, just before including header which defines the above class:
static void X::f(int);
Now the previous call X::f(0) would give linker error (unresolved name) because now 0 wouldn't convert to float, because it does not need to as there is a declared function which accepts an int, though it is not defined — worse, if it is defined, then you wont even get the linker error and you would probably not easily know that a different function is being called.
Morever. f(int) can now access the private member _data as well — in this way, anyone can access any private/protected members just by adding functions at whim.
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.
this is the cpp of a Time function. The code is defining functions of a time.h file on this time.cpp. My question is: How come this function definition is possible if the functions inside this fct are defined afterwards? Thank you
void Time::setTime(int hour, int minute, int second)
{
sethour(hour);
setminute(minute);
setseconds(seconds);
}
void Time::sethour( int h)
{ ....
You don't need a definition to call a function, you only need a declaration. The compiler is happy with the declaration alone. The linker requires code to be generated, and it requires the definition, but it doesn't matter when you define them, as long as you do.
In your case, the declaration of every member function is visible to all other member function, even if inside the class definition it came afterwards:
class Time
{
void setTime(); //setTime knows about sethour even if it's before
void sethour();
};
Outside of a class, this doesn't hold, meaning you need a declaration before using a method. The declaration is just the prototype:
void foo();
void goo()
{
foo(); //can call foo here even if it's just declared and not defined
}
Presumably because they were declared somewhere above (e.g. in the header file), and that's what's important.
It's best to imagine that the compiler operates in a "one-pass" approach; it processes your code linearly from top-to-bottom. Therefore, it needs to know that functions exist (i.e. their name, arguments and return type) before they are used, in order to establish that the caller is not doing something invalid. But the actual function definition (i.e. its body) is not relevant for this task.
You can choose when to define them.