Kevin's Guides

Where to Start

Usually, you would need to have the Clemson University VPN to access the cadence software. However, for some courses such as the C++ Language Fundamentals course, nothing but an IDE such as VSCode is necessary. Still, visit the Getting Started page to learn more about installing the VPN and Cadence software, or click here for a quick link to the software downloads.

Using Cadence's learning maps, you can see the general order of how to approach Cadence's online courses. These guides will be focusing on page 8 of that document (Design and Verification Languages). Remember that most software requires the Clemson VPN to run. 

C++ Language Fundamentals for Design and Verification

Requirements: 

General Notes:

Module 1

Aside from the normal PDF downloads necessary for every course, this lab's database also comes in a compressed format. The instructions to uncompress them assume command line knowledge -- here's a more detailed step-by-step guide to uncompressing the downloaded file:

2. Open your system's terminal (this can be done through the "terminal" application or through other apps with integrated terminals such as VSCode)

3. Navigate to your Downloads folder

4. Once you're in the proper directory, follow the instructions on the site (Note: I didn't need the "uncompress <Lab>.tar.Z" step when uncompressing the lab database, though this may vary from system to system)

Module 2

This module is a fairly straightforward introduction to object-oriented programming concepts and their respective syntactical elements in C++. It also explains some of the differences between C and C++. I would recommend paying close attention to the concepts in this module if you are new to the concept of object-oriented programming, but for those with prior experience, the most important parts will be the syntactical implementations of these concepts. 

The lab for this section is simply an intellectual exercise -- it doesn't require you to actually write any code. Use it to test your knowledge of object-oriented concepts. 

Module 3

This module serves as an introduction for C++ the language. It covers basic I/O, declarations and scope, members access specifiers, the instance pointer "this," and the new and delete operators. 

Some of the I/O terminology can get confusing if you're only used to C syntax, but luckily C's printf and scanf are still accessible in C++ for those adjusting. The concept of flushing is also mentioned but not explained, but there are plenty of outside resources on it, such as this one. The scope resolution operator mentioned is :: (two colons), as seen in the example for scope resolution. If :: is put without anything before it it defaults to global.

The concept of friend functions is also mentioned here, and will be discussed further in module 8. All friend functions must be declared within the class with the friend prefix (though no function definition is required), and then any function named that name will be able to access protected and private variables. Though it's not explicitly spelled out, you will learn in later modules that the difference between protected and private is whether subclass member functions can access the region.

The new and delete operators are very similar to malloc and free, though there are some differences which are covered here

The concept of pass-by-reference also doesn't exist in regular C, but will be explained further in module 5.

The lab for this module is fairly straightforward. Feel free to reference back to the lecture PDF for terminology. 

Module 4

This module introduces the concepts of constructors and destructors in C++. The concepts of overloading and default constructors are also introduced because of this. If you're unfamiliar with how stack and heap memory actually work in C and C++, it would likely be good to review that before going into this module. 

Similarly, the concepts of pass by reference and lvalue and rvalue expressions will not be fully introduced in module 5. For those who don't already have a background in C++, skipping forwards to learn a bit about these concepts before coming back could be prudent. I found that I myself did not fully understand the contents of modules 4 and 3 before going on to module 5 and then coming back to them.

The lab for this module is again fairly straightforward, especially as there are no requirements for class variables in dynamically allocated memory.

Module 5

This module finally introduces aliases and reference variables. These concepts are very important for understanding both the previous and next modules, so paying close attention to the nuances is imperative. One particular nuance which this module does a good job of hammering in is that C++ treats named rvalue expressions as lvalue

It should be noted that like the * operator, the & operator can be affixed to both the end of the type and the beginning of the variable name (for example, int& myIntRef and int &myIntRef are identical statements). However, the syntax presented in the course is preferred due to both * and & binding closer to variable names than to type declarations (for example, int* ptr1, ptr2; would declare ptr1 as a pointer to an int, and ptr2 as a regular integer.)

It should be noted that almost no actual modern language is considered pass-by-reference. C++ allows the operation, but the standard passing of a normal object into a function still passes only a value. When learning other languages and how they pass a "reference" of the object to the function upon calling it, it is important to note that this actually means that they are likely passing in a value of a pointer or similar.

The lab for this module is again fairly straightforward.

Module 6

This module discusses functions, and how to best use them to optimize program reliability and performance. In doing so, it covers argument passing, overloading, const/volatile modifiers, and static variables

This module also seems to repeat some content from previous modules, which may be good for review but can be skipped if you're already familiar with the content. 

The concepts of const and volatile modifiers are introduced in this module. It should be noted that in the slide covering cost/volatile qualified functions, the square brackets indicate optional inclusion (Only a const [volatile] function can act on a const object, meaning a const function or a const volatile function).

The concept of functors is also introduced, and while the lecture on functors can be a bit confusing, they essentially allow the use of an object as a function by overloading the operator() method. A good resource on functors can be found here. Lambda expressions are a special type of functor defined at the point of instantiation, and are typically used for quick in-line function declarations. The lectures go into a lot of detail about the specifics of lambda expressions, but it's ok to just go over the basics and then return to the slides if the need arises for further specific knowledge.

The lab for this module is again fairly straightforward. Here's a good resource on enumerated types if you're unfamiliar with them (or skip to the next module's reference guide).

Module 7

This module covers type conversions, both explicit and implicit. 

The quick reference guide to C++ types at the beginning of the lecture is very helpful to reference throughout the course. In general, this module contains many tables and reference sheets which are very good to keep bookmarked for future reference.

The overview of type checking and some of the differences in type checking between C and C++ is very helpful, though if you ran your C code using a C++ compiler you may already be used to most of these standards. 

The lab for this module is more of an experiment, and allows you to learn the nuances of the reinterpret_cast operator. 

Module 8

This module covers operator overloading and best practices, as well as friend operators.

The basic concepts of each of these ideas is fairly simple, though the lectures go into a lot of semantic detail with many technical examples to flesh these ideas out. We also return to the concept of functors with this new knowledge, which helps to solidify the concepts learned in previous modules. 

There are a couple of useful tables and reference guides in this module as well, with the last guideline for operator overloading being especially useful.

The lab for this module is simple, but very good for checking understanding of all the previous concepts taught in this course. It also sheds light on how some higher-level languages perform many of the basic operations which we sometimes take for granted.

Module 9

This module covers inheritance, which is a very important concept in software development as a whole. 

The first part of the module covers the broad concept of inheritance and can be very useful for those who might not have been exposed to the concepts of inheritance from other languages. The second part covers UML, which is a specific design language used for modeling software systems and includes many handy standards. It also includes an editorial about the order in which you declare class data. For further knowledge on UML, the official UML site linked on the slides or this guide can be helpful.

The section on base specifiers and the virtual base specifier is also useful when implementing objects with inheritance. 

The lab for this module is again fairly straightforward.

Module 10

This module covers polymorphism, name binding, and pure virtual functions and abstract classes.

The discussion of static vs dynamic name binding is a key detail of the C++ language, and should shed light on the use of the virtual keyword in earlier modules. 

There appears to be a typo in this module, where they say for pointer class member access operations: "For virtual functions – at time time, based on object type." I believe that this should say "runtime, based on object type."

The nuances of name binding can be very important to know for things such as keeping an array of pointers, where every pointer must be the same type. Furthermore, the concept of interfaces or abstract classes is derived from virtual name binding, as well as the pure specifier.

Please note the section on virtual destructors to prevent memory leaks.

The lab for this section is again more of an experiment, and should give you some good intuition about how many of the concepts discussed in this module work.

Module 11

This modules covers the const and constexpr specifiers and their uses and surrounding properties. 

From this module on, more and more terminology will begin to appear in the slides, especially if you're working off of the PDF rather than the regular slides. Most of it doesn't need to be memorized as much as the keywords introduced in the previous modules, as there will also be more reference guides and the like to check back to when a piece of terminology is brought up. 

The slide concerning the semantics around const member functions is worth reviewing, as the dynamics around const functions in relation to both const and non-const objects can be very useful or detrimental depending on one's understanding. Further, mutable variables and cast-to-const operations allow workarounds for these rules.

The slide reviewing the differences between the const and constexpr keywords is very useful as well.

The lab for this module is again fairly straightforward, and the exercises should give some good intuition around consts and constexprs.

Module 12

This module covers templates, both for functions and for classes, as well as their semantics.

This module has another three useful quick reference guides which can be saved for future reference. 

The concept and requires keywords are introduced for customization of the constraints around templates, which allows great flexibility and abstraction. Please note the specificity rules surrounding how a template gets chosen and the scope coexistence barrier between template and non-template.

The lab for this module is again fairly straightforward, and should allow for some practice in template creation and instantiation.

Module 13

This module covers exceptions -- a very useful concept for error handling and, as the name implies, exceptional conditions. In doing so, it covers try-catch blocks, noexcept operators, and nested exceptions. These are very important topics for "real world" code writing, and best practices in this area can benefit anyone in their coding. 

This module includes some more reference guides, as well as many good examples regarding how exceptions and exception handling is implemented in code. The references for common exceptions and exception-related functions are very good to save. Make sure to get familiar with catching and throwing and the semantics behind the two, as well as how to build your own code to gracefully use exceptions to your benefit. 

Some previous topics such a polymorphism and abstraction are brought up again in this module's context through the implementation of exception objects and nested exceptions. 

The lab for this module is fairly straightforward, and should provide some good practice in exception handling.

Module 14

This module discusses I/O streams, I/O state, formatting, and common I/O libraries.

Some of this module was covered in the first module, and the revisitation serves as a good checker for how far you've come in the course. Many of the concepts introduced in the first I/O section that may have seemed foreign should now make a lot more sense. 

Much of I/O has to do with formatting, and so rightfully this module spends a lot of time detailing the intricacies of formatting for many different aspects of I/O. It also provides more useful reference guides to help with these specifics. There are many footnotes in these lectures which provide additional knowledge on specific functions related to I/O -- these can be very good to read to fully understand what's going on in many of the slides.

The concept of delimiters and how different methods of reading and writing interact with them is very important for I/O as a whole. An additional resource can be found here.

This module covers a lot of specifics, but rather than trying to memorize it all from the slides, referencing the guides and implementing the different methods covered in the module in practice would be a much better and more organic way to learn it all should you feel the need. The common methods will naturally ingrain themselves into your memory and the uncommon methods can always be looked up when needed. This advice also generally applies to most programming concepts. 

The lab for this module is again fairly straightforward and should allow one to experience some of the intricacies discussed above firsthand.

Module 15

This module covers bugs and debugging, and teaches content that applies on a much broader level than most of the previous modules. Debugging is one of the most important skills a developer can attain, and thus this module provides some crucial background that can serve you past this course and even C++ in general. 

The module begins with an introduction to the concept of bugs, how they occur, and best practices when it comes to dealing with them. The central paradigm introduced of "don't create errors, don't let the user create errors, and find your errors early and often" is a mantra repeated by many professionals in both computer science industry and academia. 

Five general methods of debugging are then discussed, before diving into two specific debuggers: GDB and DDD. The specific instructions for debugging with GDB can prove to be very useful in one's general coding life, and can vastly optimize what would otherwise require many hours of inline print statements and messing with code. 

The lab for this module is fairly straightforward and lets you play around with some of GDB's functionalities.

Module 16

This module is comprised of three submodules, and discusses containers, almost-containers, and standard algorithms.

While very lengthy, the majority of the slides for this module are dedicated to reference guides for container and container-adjacent knowledge in C++. The specifics take up a lot of room compared to the broad concepts, and this is a module where I would recommend skimming to catch general ideas and then coming back to it if specific information is required. Many reoccurring concepts such as abstraction make their last appearances here, but the modules focus a lot more on the "whats" and "hows" than the "whys." 

The lab for this module is fittingly fairly straightforward, though you may have to reference back to the slides a lot to implement specific types of containers and functions.

Badge Exam

Congratulations! You've now completed the C++ Language Fundamentals course! The badge exam for this course is a little longer than some of the other ones and might take a couple of tries, but there are as many retakes as you need and you can always see what you got wrong. 

Also, feel free to post your badge to your LinkedIn profile and connect with David Haeussler (https://www.linkedin.com/in/david-haeussler-559392). Once you've received your badge, let Dave know, and he will gladly repost your digital badge to help maximize its visibility.