C++: Difference between revisions
Undefishin (talk | contribs) (Created page with "'''C++''' is an object-oriented programming language created by Bjarne Stroustrup in 1985 as a variant of the C programming language. It includes features not found in C such as classes, virtual dispatch inside of said classes, standardized memory allocation and deallocation, exception unwinding, and a standard library of generic utilities known as the STL (which provides containers like strings, and the vector<T> type, alongside lots more). The current standardized C++...") |
Undefishin (talk | contribs) (fix inconsistent spacing) |
||
(One intermediate revision by the same user not shown) | |||
Line 2: | Line 2: | ||
The current standardized C++ version is C++20, which added the "consteval" keyword and the Concepts TS, among lots of other improvements. |
The current standardized C++ version is C++20, which added the "consteval" keyword and the Concepts TS, among lots of other improvements. |
||
The C++ language has played a big role in CollabVM's history, most notably in CollabVM version 1.1 and onward, which is the rewrite of the CollabVM server by Cosmic Sans, along with CollabVM 2.0 also by Cosmic. It is also used in CollabVM 3.0 by modeco80, which is similarly known as a prolific and incredibly talented C++ programmer. |
|||
== Examples == |
== Examples == |
||
=== Hello World === |
=== Hello World === |
||
This program prints out "Hello, world!" to the console. |
This program prints out "Hello, world!" to the console. |
||
Line 13: | Line 13: | ||
int main() { // Main function: must return a variable of int type. This is the program's exit code. |
int main() { // Main function: must return a variable of int type. This is the program's exit code. |
||
std::cout << "Hello, world!\n"; |
|||
return 0; // Quit with the exit code of 0 |
|||
} |
} |
||
</syntaxhighlight> |
</syntaxhighlight> |
||
=== Fizz Buzz === |
=== Fizz Buzz === |
||
This is a more complex example: this program prints out "Fizz" for each multiple of 3, "Buzz" for each multiple of 5, and "Fizz Buzz" for each multiple of both. This program demonstrates functions besides <code>main()</code>, the <code>if</code> statement, the ternary operator (<code>condition ? ifTrue : ifFalse</code>), and loops. |
This is a more complex example: this program prints out "Fizz" for each multiple of 3, "Buzz" for each multiple of 5, and "Fizz Buzz" for each multiple of both. This program demonstrates functions besides <code>main()</code>, the <code>if</code> statement, the ternary operator (<code>condition ? ifTrue : ifFalse</code>), and loops. |
||
Line 28: | Line 27: | ||
enum class FizzBuzzType { |
enum class FizzBuzzType { |
||
None, |
None, |
||
FizzBuzz, |
FizzBuzz, |
||
Fizz, |
Fizz, |
||
Buzz |
Buzz |
||
}; |
}; |
||
FizzBuzzType GetFizzBuzzType(int number) { |
FizzBuzzType GetFizzBuzzType(int number) { |
||
if(number % 3 == 0 && number % 5 == 0) { |
|||
return FizzBuzzType::FizzBuzz; |
|||
} |
|||
if(number % 3 == 0) { |
|||
return FizzBuzzType::Fizz; |
|||
} |
|||
if(number % 5 == 0) { |
|||
return FizzBuzzType::Buzz; |
|||
} |
|||
return FizzBuzzType::None; |
|||
} |
} |
||
int main() { |
int main() { |
||
// i starts as 1, the loop continues until it is above 100, and i increments each loop. |
|||
for(int i = 1; i <= 100; i++) { |
|||
// This refactored switch statement is better than before. |
|||
// It also calculates the value only once. |
|||
switch(GetFizzBuzzType(i)) { |
|||
case FizzBuzzType::FizzBuzz: |
|||
i < 100 ? std::cout << "Fizz Buzz, " : std::cout << "Fizz Buzz" << '\n'; |
|||
break; |
|||
case FizzBuzzType::Fizz: |
|||
i < 100 ? std::cout << "Fizz, " : std::cout << "Fizz" << std::endl; |
|||
break; |
|||
case FizzBuzzType::Buzz: |
|||
i < 100 ? std::cout << "Buzz, " : std::cout << "Buzz" << std::endl; |
|||
break; |
|||
case FizzBuzzType::None: |
|||
i < 100 ? std::cout << i << ", " : std::cout << i << '\n'; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
return 0; |
return 0; |
||
} |
} |
||
</syntaxhighlight> |
</syntaxhighlight> |
||
== Virtual Functions == |
== Virtual Functions == |
||
Virtual functions are functions part of a class which can be implemented in another inheriting class, allowing the actual implementation to be located somewhere else or even hidden from code. |
Virtual functions are functions part of a class which can be implemented in another inheriting class, allowing the actual implementation to be located somewhere else or even hidden from code. |
||
The example code here shows how a completely abstract class can be implemented inside of a different translation unit (source file), so that the main program only needs |
The example code here shows how a completely abstract class can be implemented inside of a different translation unit (source file), so that the main program only needs the interface to work. |
||
the interface to work. |
|||
Interface.h: |
Interface.h: |
||
Line 97: | Line 94: | ||
// and also sets this class up for proper RTTI data generation. |
// and also sets this class up for proper RTTI data generation. |
||
virtual ~MyInterface() = default; |
virtual ~MyInterface() = default; |
||
// Do something. |
// Do something. |
||
virtual void Run() = 0; |
virtual void Run() = 0; |
||
Line 113: | Line 110: | ||
namespace { |
namespace { |
||
// Implements MyInterface. |
|||
class MyInterfaceImpl : public MyInterface { |
class MyInterfaceImpl : public MyInterface { |
||
public: |
public: |
||
Line 140: | Line 137: | ||
== Generic code == |
== Generic code == |
||
C++ supports "templates" which are the front and center way of writing generic code. Alongside this, is now the Concepts TS, allowing us to |
C++ supports "templates" which are the front and center way of writing generic code. Alongside this, is now the Concepts TS, allowing us to |
||
with ease constrain what types a template can operate on. |
with ease constrain what types a template can operate on. |
||
Line 185: | Line 181: | ||
} |
} |
||
</syntaxhighlight> |
</syntaxhighlight> |
||
[[Category:Programming Languages]] |
[[Category:Programming Languages]] |
Latest revision as of 17:48, 14 January 2024
C++ is an object-oriented programming language created by Bjarne Stroustrup in 1985 as a variant of the C programming language. It includes features not found in C such as classes, virtual dispatch inside of said classes, standardized memory allocation and deallocation, exception unwinding, and a standard library of generic utilities known as the STL (which provides containers like strings, and the vector<T> type, alongside lots more).
The current standardized C++ version is C++20, which added the "consteval" keyword and the Concepts TS, among lots of other improvements.
The C++ language has played a big role in CollabVM's history, most notably in CollabVM version 1.1 and onward, which is the rewrite of the CollabVM server by Cosmic Sans, along with CollabVM 2.0 also by Cosmic. It is also used in CollabVM 3.0 by modeco80, which is similarly known as a prolific and incredibly talented C++ programmer.
Examples
Hello World
This program prints out "Hello, world!" to the console.
#include <iostream>
int main() { // Main function: must return a variable of int type. This is the program's exit code.
std::cout << "Hello, world!\n";
return 0; // Quit with the exit code of 0
}
Fizz Buzz
This is a more complex example: this program prints out "Fizz" for each multiple of 3, "Buzz" for each multiple of 5, and "Fizz Buzz" for each multiple of both. This program demonstrates functions besides main()
, the if
statement, the ternary operator (condition ? ifTrue : ifFalse
), and loops.
It also shows the use of the new strongly typed "enum class" kind of enums and the switch() statement.
#include <iostream>
enum class FizzBuzzType {
None,
FizzBuzz,
Fizz,
Buzz
};
FizzBuzzType GetFizzBuzzType(int number) {
if(number % 3 == 0 && number % 5 == 0) {
return FizzBuzzType::FizzBuzz;
}
if(number % 3 == 0) {
return FizzBuzzType::Fizz;
}
if(number % 5 == 0) {
return FizzBuzzType::Buzz;
}
return FizzBuzzType::None;
}
int main() {
// i starts as 1, the loop continues until it is above 100, and i increments each loop.
for(int i = 1; i <= 100; i++) {
// This refactored switch statement is better than before.
// It also calculates the value only once.
switch(GetFizzBuzzType(i)) {
case FizzBuzzType::FizzBuzz:
i < 100 ? std::cout << "Fizz Buzz, " : std::cout << "Fizz Buzz" << '\n';
break;
case FizzBuzzType::Fizz:
i < 100 ? std::cout << "Fizz, " : std::cout << "Fizz" << std::endl;
break;
case FizzBuzzType::Buzz:
i < 100 ? std::cout << "Buzz, " : std::cout << "Buzz" << std::endl;
break;
case FizzBuzzType::None:
i < 100 ? std::cout << i << ", " : std::cout << i << '\n';
break;
}
}
return 0;
}
Virtual Functions
Virtual functions are functions part of a class which can be implemented in another inheriting class, allowing the actual implementation to be located somewhere else or even hidden from code.
The example code here shows how a completely abstract class can be implemented inside of a different translation unit (source file), so that the main program only needs the interface to work.
Interface.h:
#include <memory>
// This class is "abstract" meaning it does not implement any of the virtual functions.
// A more sophisticated interface can provide non-virtual functions as well as
// base-class implementations of some virtual functions.
class MyInterface {
public:
// Declare a virtual destructor.
// This makes destructing a MyInterface* not leak memory,
// and also sets this class up for proper RTTI data generation.
virtual ~MyInterface() = default;
// Do something.
virtual void Run() = 0;
};
// Creates a thing which implements the above interface.
// Essentially a stateless factory.
std::shared_ptr<MyInterface> CreateAThing();
Interface.cpp:
#include "Interface.h"
#include <cstdio>
namespace {
// Implements MyInterface.
class MyInterfaceImpl : public MyInterface {
public:
virtual void Run() override {
std::printf("MyInterfaceImpl::Run()\n");
}
};
}
std::shared_ptr<MyInterface> CreateAThing() {
return std::make_shared<MyInterfaceImpl>();
}
main.cpp:
#include "Interface.h"
int main() {
auto interface = CreateAThing();
thing->Run();
return 0;
}
Generic code
C++ supports "templates" which are the front and center way of writing generic code. Alongside this, is now the Concepts TS, allowing us to with ease constrain what types a template can operate on.
#include <concepts>
// This concept constrains to types
// which can perform arithmetic.
template <class T>
concept Arithmetic = requires(T left, T right) {
{ left + right } -> std::same_as<T>;
{ left - right } -> std::same_as<T>;
{ left * right } -> std::same_as<T>;
{ left / right } -> std::same_as<T>;
// This maybe shouldn't also be checking for
// EqualityComparable and LessThanComparable?
{ left < right } -> std::same_as<bool>;
{ left > right } -> std::same_as<bool>;
{ left <= right } -> std::same_as<bool>;
{ left >= right } -> std::same_as<bool>;
{ left == right } -> std::same_as<bool>;
{ left != right } -> std::same_as<bool>;
};
// A (pretty useless) sample of concepts.
// This template is properly constrained to only
// work on arithmetic types, and none else.
// If a user defined type is considered arithmetic,
// this code will automatically work.
template <Arithmetic T, Arithmetic Y>
T Add(T left, Y right) {
return left + right;
}
struct S{};
int main() {
return Add(1, 2);
// Uncomment to see what happens; it won't be 50 lines
// of template errors.
//return Add(S{}, 21);
}