מבחינת התכנות הגנרי, מאפשרת שימוש בתבניות (templates). התבניות מאפשרות כתיבת קוד כללי יעיל, ללא תלות בהיררכית הורשה. תומכת בתבניות הן לפונקציות והן למחלקות. בנוסף, קיימת טכניקת תכנות בשם "Template Meta-Programming" (TMP) המהווה בעצם "תת־שפה" נפרדת, פונקציונלית, המנצלת את התבניות על מנת לאפשר ביצוע חישובים מורכבים בזמן הידור (בגרסאות מאוחרות של השפה ניתן לבצע חישובים כאלה גם ללא תבניות). בנוסף, שפת ++C ירשה את מנגנון המאקרו של שפת C, על יתרונותיו וחסרונותיו.
C תוכננה כך שהיא שומרת על תאימות לאחור עם שפת C במידה רבה מאוד. ברוב המקרים, קוד הכתוב בשפת C יהודר וירוץ באותה דרך גם בעזרת מהדר של ++C, בעזרת שינויים מינוריים או ללא שינויים כלל. מתוכננת על מנת לשמור על היעילות והגמישות בהן מצטיינת שפת C, ולכן גם היא מהודרת על פי רוב ישירות לשפת מכונה (זאת בניגוד לשפות #C ו־Java המתורגמות לרוב לשפת ביניים המורצת על ידי מכונה וירטואלית) ומקפידה לאפשר גישה ישירה אל זיכרון המחשב. מנגנונים המוסיפים תקורה מסוימת (לדוגמה חריגות או RTTI) לא פוגעים בזמן הריצה אלא אם כן חל שימוש בהם. עיקרון חשוב בשפה הוא שליטה מלאה של המתכנת על הפעולות שמתבצעות בזמן ריצה. עיקרון זה שולל הפעלה של מנגנון איסוף זבל (אם כי ישנה אפשרות כזאת, בה נעשה שימוש לעיתים רחוקות). תחת זאת, ניהול משאבי מערכת מתבצע לרוב בטכניקה שנקראת RAII, בה ניהול של משאב מתנהל דרך אובייקט המוקדש לכך: "מצביעים חכמים" או אוספים כגון Vecto.
השפה כוללת מערכת טיפוסים סטטית מורכבת, שתפקידה לגלות שגיאות בזמן הידור התוכנית ולאפשר יצירת תוכניות יעילות יותר.
מושגים בשפה.
מרבית המושגים הבסיסיים בשפת C קיימים בצורה זהה או דומה מאוד גם בשפת ++C.
להלן תוספות בשפת ++C שאינן קיימות בשפת C.
מחלקה.
המחלקה (Class) היא לב לבה של השפה. המחלקה היא תיאור של טיפוס הכולל נתונים ופעולות שאפשר לבצע על הנתונים. משתנים מסוג אותו טיפוס נקרא "עצמים" (Objects).
המחלקה כוללת משתנים (Data members) ושיטות (Member functions או Methods). השיטות הן פונקציות שפועלות על המשתנים של המחלקה. שני סוגים חשובים של שיטות הם פונקציות הבנייה (Constructors) ופונקציית ההריסה (Destructor) אשר תפקידן הוא לאתחל עצם מהמחלקה ולמחוק את תוכנו כאשר הוא נמחק.
הגבלת גישה.
הגבלת הגישה לרכיבי המחלקה השונים מהווה כלי מרכזי למימוש עקרון הכימוס. ישנן שלוש רמות של הגבלות גישה:
כמו כן ניתן להגדיר פונקציה או מחלקה מסוימת כחבר (Friend). חברי המחלקה מקבלים גישה לכל המשתנים, השיטות והטיפוסים שמוגדרים במחלקה, גם לפרטיים וגם לשמורים.
הורשה.
ניתן להגדיר מחלקה נורשת ("Derived class") על סמך מחלקה אחרת, בסיסית ("Base class"). המחלקה הנורשת מכילה אוטומטית את המשתנים, השיטות ושאר רכיבי המחלקה הבסיסית ובנוסף מגדירה כאלו משל עצמה. לעומת שפות מודרניות אחרות שמתבססות עליה, תומכת בהורשה מרובה, כלומר ירושה ממספר מחלקות בו זמנית.
כאשר מורישים תכונות למחלקה אחת ממחלקה שנייה ניתן לעשות זאת באחת משלוש דרכים:
ניתן להתייחס לעצם דרך מצביע או ייחוס (Reference) למחלקה בסיסית, ולהפעיל שיטות של העצם בלי לדעת מראש את הטיפוס המדויק שלו. שיטות כאלו מוגדרות "וירטואליות". הן ניתנות להפעלה על ידי התייחסות לעצם ממחלקה בסיסית אך בפועל מבוצעת המתודה במחלקה הנורשת, בהתאם לסוג העצם עבורו הופעלה המתודה. זהו סוג מסוים של פולימורפיזם (הסוג האחר הוא תכנות גנרי בעזרת תבניות - ראה בהמשך).
מנגנון ה־Run-Time Type Information (RTTI) מאפשר לקבל מידע על הטיפוס של העצם הנתון, תוך כדי ריצת התוכנית. מנגנון זה מגדיר את האופרטור dynamic_cast שמאפשר לבצע המרה בטוחה בין מצביע (או הפנייה) למחלקת בסיס לבין מצביע למחלקה הנגזרת. אופרטור זה מאפשר לבדוק האם העצם הנתון הוא מטיפוס מסוים או לא. אופרטור נוסף שנוסף לשפה במסגרת ה־RTTI הוא אופרטור ה־typeid. אופרטור זה מאפשר לקבל את הטיפוס המדויק של העצם הנתון.
לעומת שפות אחרות, כמו לדוגמה, ב־ אין הבדל בין מחלקות (class) לבין מבנים (struct). גם מחלקות וגם מבנים יכולים להכיל שיטות, לרשת האחד מהשני, להגדיר פונקציות וירטואליות ולהגדיר רמות גישה שונות. ההבדל היחיד הוא שתכונות המבנה מוגדרות ציבוריות כברירת מחדל ואילו תכונות המחלקה כפרטיות.
טיפוסיות חזקה.
מערכת הטיפוסים בשפה חזקה יותר מזו שבשפת C. בשפת C, המהדר מבצע המרות טיפוסים בצורה אוטומטית ובקלות יחסית, ובה ניתן להשתמש במצביע *void שיכול להצביע אל אובייקט מכל טיפוס.
בשפת הוקשחו הכללים והמרות טיפוסים מובלעות נעשות רק לפי הגדרות המובנות בשפה או כאלה שהוגדרו על ידי המשתמש. שימוש ב-*void דורש המרה מפורשת, ולכל סוג של המרה ישנו אופרטור מפורש מתאים (static_cast, dynamic_cast, const_cast, reinterpret_cast). תכונה זו מאפשרת גילוי שגיאות רבות יותר בשלב ההידור וחוסכת את מציאתן המייגעת בזמן הריצה.
בשל הגישה הכללית של השפה לאפשר למתכנת לבצע כל פעולה, בתנאי שברור שהוא באמת מעוניין בכך, הטיפוסיות בשפה בטוחה פחות מאשר בשפת Java, למשל.
הגדרת הקבוע.
את הגדרת הקבוע codice_1 ניתן להצמיד למשתנה של מחלקה, לפרמטר של מתודה או פונקציה, לערך המוחזר מהן וכן למתודה עצמה. הוספת ה-qualifier למשתנה מצהירה על כך שהמשתנה לא ישתנה אחרי שהוא אותחל. כך מתאפשר למהדר לגלות שגיאות ולייצר קוד יעיל, ומונע מהמשתמש לשנות אובייקטים בטעות. הצמדה של ה-qualifier למתודה, מצהירה על כך שהמתודה הזאת יכולה להיקרא מתוך אובייקט של המחלקה שהוגדר כ-const.
ה־Const מוגדר היטב עבור טיפוסים סקלריים, אך עבור מחלקות הוא עשוי שלא להיות מספק, וזאת מכיוון שהמהדר מוודא שהבתים בזיכרון ששייכים לאובייקט לא משתנים אך אינו בודק דבר פרט לזה. בעיות אפשריות שיכולות לנבוע מכך כוללות:
פתרון לבעיה הראשונה הוא עקרון הכימוס - המחלקה תחשוף בממשק שלה עבור אובייקטים קבועים אך ורק מתודות שלא משנות את נתוני המחלקה.
פתרון לבעיה השנייה הוא ה-qualifier codice_2, שמאפשר שינוי של משתנים באובייקט של המחלקה גם כאשר האובייקט מסומן כ-const. כעיקרון תכנותי, מוצע כלל M&amp;M - "Mutable and Mutex go together"
הצוויה (Reference).
ניתן להגדיר משתנים, פרמטרים וערכים מוחזרים כמתייחסים לעצם (Reference). הייחוס דומה מאוד להצבעה: כמה משתנים יכולים להתייחס לאותו עצם ולפעול עליו במשותף, כמו שמצביעים שונים יכולים לפעול על אותו עצם. ישנם מספר הבדלים מהותיים בין מצביע לייחוס: מצביע יכול להיות לא מאותחל, ואילו ייחוס תמיד יתייחס לעצם כלשהו. כמו כן ניתן לשנות הצבעה של מצביע אבל לא ניתן לשנות ייחוס, הייחוס נקבע לכל אורך חייו של הייחוס. מבחינה תחבירית השימוש בייחוס הוא כמו בעצם עצמו.
העמסת פונקציות.
העמסת פונקציות היא היכולת להשתמש באותו השם לפונקציות (או שיטות) שונות, בתנאי שישנו הבדל ביניהן במספר הפרטרים או בטיפוסי הפרמטרים אותם הן מקבלות. הדבר מאפשר להגדיר מספר רב של פונקציות שמבחינה לוגית מבצעות פעולה דומה אך מקבלות פרמטרים שונים. תכונה זו מאפשרת לכתוב קוד קריא יותר, אם כי הגזמה בהעמסת פונקציות עשויה ליצור אי־בהירות או מקרים של דו־משמעות.
פרמטרים אופציונליים.
דרך נוספת להעמיס פונקציות היא להגדיר ערכי ברירת מחדל לפרמטרים של מתודה או פונקציה. אם מתבצעת קריאה לפונקציה שאיננה כוללת ערך עבורם, הם יקבלו את ערך ברירת המחדל. כך ניתן בקלות להגדיר פעולה זהה עבור מספר שונה של פרמטרים, מבלי לבצע שכפולי קוד.
כאמור, ניתן לכתוב ב-++C את כל הקשת, מתכנות פרוצדורלי עם טיפוסיות חלשה בדומה לשפת C ועד לניצול פרדיגמות התיכנות המודרניות ביותר. מסיבה זו ניתן, אך לא מומלץ, לכתוב פונקציות המקבלות מספר בלתי מוגדר מראש של פרמטרים, על ידי שימוש בשלוש נקודות (...) בחתימת הפונקציה - נקרא Ellipsis parameter. תכונה זו קיימת רק על מנת להקל על הגירה של תוכניות משפת C לשפת ++C. את ה־"Printf" של C, שהיא דוגמה לפונקציה עם מספר פרמטרים משתנה (...), מחליפות ב-++C מחלקות כגון iostream המאפשרות לשרשר פרמטרים להדפסה תוך שימוש בהעמסת אופרטורים וטיפוסיות חזקה. במידה ומשתמש רוצה לקבל מספר לא ידוע של משתנים לתוך פונקציה, מאפשרת העברת Parameter pack.
העמסת אופרטורים.
בשפה קיים מנגנון העמסת אופרטורים. כלומר, ניתן להגדיר מחדש כמעט כל אופרטור זמן ריצה המוגדר בשפה כך שהוא יהיה בעל משמעות עבור טיפוסים שונים, כולל טיפוסים המוגדרים על ידי המשתמש. למשל, אופרטור החיבור (+) בצורתו הרגילה מאפשר חיבור שני משתנים המכילים ערך מספרי. אך ניתן להגדיר אותו כך שיהיה בעל משמעות גם עבור משתנים מטיפוס שבר שהוגדר על ידי המתכנת.
אין כל הבדל סמנטי בין העמסת אופרטורים להעמסת פונקציות, שכן ההבדל בין אופרטורים לפונקציות הוא תחבירי בלבד. שימוש בהעמסה עשוי לשפר את קריאות הקוד, ושימוש מוגזם עשוי להפוך קוד לבלתי קריא.
תבניות (Templates).
שפת תומכת ב־Templates – תבניות. התבניות מהוות רמת הפשטה נוספת מעל רמת ההפשטה של המחלקה. הן מאפשרות יצירת מחלקות או פונקציות על ידי תבנית, כאשר בכל פעם הפונקציה או מחלקה נוצרת עבור טיפוס או טיפוסים אחרים. ה"טיפוס" הוא טיפוס פשוט או מחלקה בעצמו. הטיפוסים "מועברים" בכמעין פרמטר על ידי שימוש בסוגריים זוויתיים: "&lt;...&gt;" במקום השימוש ב "(...)" הרגילים. המהדר מזהה אילו פרמטרים הועברו לתבנית ומשכפל את התבנית בהתאם.
Template Metaprogramming.