- [Instructor] Creating your own functions
is a fundamental part of C++ programming.
It's also the basis of methods and classes.
So let's take a look at how to create a function in C++.
And we have a very simple function here.
And all it does is it prints out a message that says
this is func.
A function is declared with a return type.
In this case, the return type is void,
which means nothing is returned from this function,
followed by the function name,
followed by a pair of parentheses.
The parenthesis may or may not include parameters.
The body of the function is a block of code in curly braces.
Notice that main is also a function,
as a return type which is int.
The name of the function, parentheses,
which sometimes does include parameters even for main.
And a block of code in curly braces.
So when I build and run this,
you'll notice that main prints, this is main,
and then it calls func, which prints this is func.
So our results should be, this is main followed
by this is func, and I'll build and run this.
And you'll see that that's exactly what we get.
A function must be declared before it is called.
If I move this function to after main.
Now when I try to build you notice
I get an error that says use of undeclared identifier func.
Because func has not yet been declared before it's called.
So what I can do is I can come up here and I can declare it.
I can say void func, and just put a semi-colon there.
And that's just a declaration
with the actual definition of the function later,
but this tells the compiler, there's a function,
and it's called this and this is its function signature.
And so it's okay to call it and we can link it up later.
And so now I can build and run
and it works exactly as expected.
It's common to put these declarations in a header file.
And so I can take this header file here that says func.H,
and I can copy it into my working project.
And then I can say up here, I can say include func.H.
And now, it'll build and run just as if I had declared
it because inside of func.H is the function declaration,
the forward declaration.
And this is actually very common to have a header file
with your function declarations
and other declarations that are used
in a program that doesn't necessarily have
to clutter up the program.
Parameters are passed to a function by declaring
them inside the parentheses of the function definition,
and passing them in the parentheses of the function call.
Let's pass an integer to this function.
I'll start by declaring the parameter
inside the parenthesis here in the function definition,
I'll say int I, so it's going to take an integer,
and then I'll replace this puts with a printf,
to print the value of I.
And now down here in main I can pass a value.
I can say 42.
And when I build and run, you notice that it says
the value is 42.
So I've passed this literal integer, I've passed it.
And it's I, once it gets into the function,
and we print it out.
So by default, functions in C++ pass variables by value.
So if instead of this literal, I declare a integer,
I'll call it I again, and I'll give it this value here.
And then I pass I to the function.
And then if I come up here in the function
and I change that value and I say I equals 73,
what do we expect to have happened?
Well, because it's passed by value.
We take this I here and we pass the function
and its value is actually copied into a new variable,
a new integer called I,
and that's the I here that's set to 73.
So this will print the value 73.
But down here, if we want to print it again,
we say printf, the value is percent I,
and I'll just say the value after func.
And that should still be 47,
because we're passing the 47 here.
But this I is actually an entirely different variable
than this I.
So when I build and run, you see it says the value 73 inside
the function, but the value after func is still 47.
Now, if you do want to actually change the source variable
and that's what's called a side effect.
If you want this to actually affect this,
that's called a side effect,
and you can accomplish this with a reference.
And all I have to do is come up here
and change this I to a reference.
And now this I is the same variable as this I.
It's not making a copy anymore.
It's just saying, oh okay, I'll use that same one
because we're passing as a reference now instead of a value.
And so when I build and run,
you'll notice that the value after func is now 73.
All I did was insert that reference operator there,
and now it takes the reference rather than making
a copy of the variable.
So this is obviously pretty dangerous.
If I have this function like often a library someplace,
and it's actually changing the values in my main program
without telling me that it's doing that.
You can see where this could create bugs
and really have somebody pulling their hair out trying
to figure out what's going on.
And so this is why it's commonly considered good practice
to put the const identifier
before this reference in the function.
And this specifically disallows the changing
of that variable.
You notice I got this error here.
It says, cannot assign to variable I
with const-qualified type const int reference.
So a whole other way to do this is with a pointer.
And this is common especially when interfacing
with libraries that are written in C and not C++,
because regular C doesn't have references.
And so it accomplishes call by reference by using pointers,
which are actually more explicit than the reference.
You don't get the unintended side effects with a pointer.
So here I would say int pointer I,
and then I would dereference this,
with the dereference operator.
And then I have to actually pass the address
of the variable using again,
it's the reference operator, but in this context
it's usually called the address of operator.
And so now when I build and run,
we still have this side effect.
The value after function is 73,
but you notice that now I don't really have any question
of why, because I actually passed the address
of this variable.
So it's more explicit.
And I have more reason to understand
and to expect side effects when I'm passing a pointer
rather than just a variable.
But again, it's good practice.
And you can protect this variable
from side effects by using the const modifier there
and now we get this error, read-only variable
is not assignable.
It's worth noting that internally values are passed
to and from a function
on a small data structure called a stack.
The stack is a relatively small space
and requires processing power to manage passing large values
to a function requires copying larger amounts
of data on the stack, and this can be time-consuming.
It can cause the stack to overflow,
which can crash your program,
and create security vulnerabilities.
So when you pass something larger than a simple value,
you'll usually want to use a reference or a pointer.
So for example here, if I include the string library here,
the STL string library,
we'll define a string object here in main.
So that's an STL string, which is an object.
It is not a C string.
And so that S does not represent a pointer.
It actually represents an object.
And so if I want to be able to pass a string object
to my function here,
then I need to obviously change my parameter list.
And I'm going to say const standard string, reference S,
because I don't want to pass the whole string object
on the stack.
That's considered bad practice
and it can lead to all kinds of problems.
And so instead, I'm passing a reference,
and because I'm passing a reference
I'm using the const modifier
because that's the safe and correct way to pass a reference.
And now here I can just say the value is,
and S.C string,
and that will return a C string that I can print
with print F.
And then down here, I can pass S just like that.
And when I build and run, it works as we expected.
So this is the accepted way to pass larger
than simple scalar values into a function,
using a reference.
And almost always it's going
to be a const qualified reference.
By default, C++ function parameters are passed
by value and on a stack.
You can pass pointers or references if you need
to pass larger values,
but you need to do so explicitly and safely.
(upbeat music)