Tuesday, October 13, 2026
HomeC ProgrammingInheritance in C++: Entry, Constructors and Overriding

Inheritance in C++: Entry, Constructors and Overriding


Delete a derived object by a pointer to a base class that has no digital destructor, and this system prints nothing uncommon and exits with standing 0. The derived destructor by no means ran, and the 65 bytes its string member allotted have been by no means freed. GCC and Clang compiled it with no warning underneath -Wall -Wextra. Most of what goes improper with inheritance in C++ seems like this: the syntax takes one line, and the foundations that make it secure are invisible till the place they’re.

This information covers inheritance in C++ from the primary derived class to the foundations that hold a hierarchy appropriate: public, protected and personal inheritance, the order constructors and destructors run in, inheriting constructors, title hiding and the scope operator, digital, override and closing, and two errors that no compiler flags. A number of inheritance and the diamond drawback have their very own information. Each program was compiled and run for this text on Ubuntu 24.04 with GCC 13.3 and Clang 18.1.3 underneath -std=c++17 and -std=c++20 with -Wall -Wextra -pedantic, and runs underneath AddressSanitizer and UndefinedBehaviorSanitizer; the examples that should not compile are proven with the errors each compilers gave. All output is captured verbatim, and the code is in a GitHub repository whose construct repeats these checks on every commit.

The Quick Reply

What’s inheritance in C++? Defining a brand new class from an present one: class Supervisor : public Worker. The derived class accommodates all the things the bottom class has and provides its personal members, and a Supervisor can be utilized wherever an Worker& or Worker* is predicted.

What’s the default inheritance in C++? Personal for a class, public for a struct. class D : B makes each public member of B non-public in D, which is never what was meant, so write public explicitly.

Does a base class want a digital destructor? Sure, if objects of a derived class will ever be deleted by a pointer to the bottom. With out one, that delete is undefined habits ([expr.delete]/3); within the check under, the derived destructor silently by no means ran.

What Is Inheritance in C++?

Inheritance in C++ is a method to outline a category (the derived class) when it comes to an present class (the bottom class). The derived class accommodates a base-class subobject with the entire base’s members, can add knowledge and features, and might override the bottom’s digital features. With public inheritance, a derived object can be utilized wherever a reference or pointer to the bottom is predicted.

The vocabulary varies between languages, so it helps to repair it as soon as:

C++ time period Additionally known as Instance
Base class Mother or father class, superclass Worker
Derived class Youngster class, subclass Supervisor
Public inheritance “is-a” relationship class Supervisor : public Worker
Overriding Changing a digital operate in a derived class double price(double) const override
Base-class subobject The bottom half inside a derived object The Worker inside each Supervisor

Inheritance as an object-oriented concept, with the identical instance in Java and Python, is roofed in inheritance in object-oriented programming. The remainder of this web page is about how C++ implements it.

A First Derived Class

A Supervisor is an Worker with an inventory of direct studies:

// fundamentals.cpp - a derived class reuses its base class's members and provides its personal.
#embody <iostream>
#embody <string>
#embody <utility>
#embody <vector>

class Worker {
public:
    Worker(std::string title, double wage) : name_(std::transfer(title)), salary_(wage) {}

    const std::string& title() const { return name_; }
    double wage() const { return salary_; }
    void increase(double p.c) { salary_ += salary_ * p.c / 100.0; }

non-public:
    std::string name_;
    double salary_;
};

// A Supervisor is an Worker, plus an inventory of direct studies.
class Supervisor : public Worker {
public:
    Supervisor(std::string title, double wage) : Worker(std::transfer(title), wage) {}

    void add_report(const Worker& e) { reports_.push_back(e.title()); }
    std::size_t team_size() const { return reports_.measurement(); }

non-public:
    std::vector<std::string> reports_;
};

void print_badge(const Worker& e) {          // accepts a Supervisor too
    std::cout << "badge: " << e.title() << 'n';
}

int fundamental() {
    Worker dev("Ada", 5000);
    Supervisor lead("Grace", 7000);

    lead.add_report(dev);
    lead.increase(10);                            // inherited from Worker

    std::cout << lead.title() << " earns " << lead.wage()
              << " and manages " << lead.team_size() << " personn";
    print_badge(dev);
    print_badge(lead);
}

Output:

Grace earns 7700 and manages 1 particular person
badge: Ada
badge: Grace

Three issues occurred with none code in Supervisor asking for them:

  • lead.increase(10) and lead.title() are inherited. Supervisor declares neither; they’re Worker‘s public member features, and public inheritance retains them public. The wage went from 7000 to 7700.
  • The bottom half is constructed first. Supervisor‘s constructor passes the title and wage to Worker(std::transfer(title), wage) in its initializer listing. That’s the solely method to initialize Worker‘s non-public members, as a result of Supervisor can not contact them immediately.
  • A Supervisor is accepted the place an Worker is predicted. print_badge(const Worker&) took each objects. Taking the parameter by reference issues: handed by worth, the Supervisor can be copied right into a plain Worker, which is known as slicing and is proven in object-oriented programming in C++.

If the bottom class has no default constructor, the derived constructor should name one explicitly. Leaving it out is a compile error, and Clang’s message says precisely why:

// missing_base_ctor.cpp - should not compile: Base has no default constructor,
// so Derived's constructor has to name one in every of Base's constructors.
#embody <string>

class Base {
public:
    specific Base(std::string title) : name_(title) {}
non-public:
    std::string name_;
};

class Derived : public Base {
public:
    Derived() {}               // which Base constructor? none may be known as
};

int fundamental() { Derived d; }

GCC first, then Clang:

exams/compile-fail/missing_base_ctor.cpp:14:15: error: no matching operate for name to 'Base::Base()'
exams/compile-fail/missing_base_ctor.cpp:14:5: error: constructor for 'Derived' should explicitly initialize the bottom class 'Base' which doesn't have a default constructor

Entry Management: public, protected and personal Inheritance

Two separate issues management entry in a hierarchy. The member’s entry (public, protected, non-public within the base) decides what the derived class can attain. The inheritance mode (public, protected, non-public earlier than the bottom title) decides what everybody else can attain by the derived class.

// entry.cpp - what a derived class can attain in its base class.
#embody <iostream>

class Base {
public:
    int pub = 1;
protected:
    int prot = 2;
non-public:
    int priv = 3;
    pal void show_private(const Base&);
};

void show_private(const Base& b) { std::cout << "pal sees priv = " << b.priv << 'n'; }

class Derived : public Base {
public:
    void present() const {
        std::cout << "Derived sees pub = " << pub << ", prot = " << prot << 'n';
        // priv isn't accessible right here: see exams/compile-fail/private_member.cpp
    }
};

struct FromStruct : Base {};          // struct: public inheritance by default
class FromClass : Base {              // class: non-public inheritance by default
public:
    int read_pub() const { return pub; }   // nonetheless seen inside the category
};

int fundamental() {
    Derived d;
    d.present();
    std::cout << "exterior sees d.pub = " << d.pub << 'n';
    show_private(d);

    FromStruct s;
    std::cout << "struct-derived: s.pub = " << s.pub << 'n';
    FromClass c;
    std::cout << "class-derived: c.read_pub() = " << c.read_pub() << 'n';
}

Output:

Derived sees pub = 1, prot = 2
exterior sees d.pub = 1
pal sees priv = 3
struct-derived: s.pub = 1
class-derived: c.read_pub() = 1

Derived learn pub and prot however not priv. A non-public member is non-public to the category that declares it, together with from its personal derived courses; solely the category and its buddies can see it, which is how show_private learn it. Reaching for a non-public member from a derived class doesn’t compile:

// private_member.cpp - should not compile: a derived class can not learn its
// base class's non-public members.
class Base {
non-public:
    int secret = 42;
};

class Derived : public Base {
public:
    int peek() const { return secret; }
};

int fundamental() { return Derived{}.peek(); }
exams/compile-fail/private_member.cpp:10:31: error: 'int Base::secret' is non-public inside this context
exams/compile-fail/private_member.cpp:10:31: error: 'secret' is a non-public member of 'Base'

The inheritance mode then modifications how inherited members look from exterior:

Member in base public inheritance protected inheritance non-public inheritance
public public in derived protected in derived non-public in derived
protected protected in derived protected in derived non-public in derived
non-public not accessible not accessible not accessible

Public inheritance is the one meaning “is-a” and permits a Derived& to transform to a Base& anyplace; it’s what you need virtually each time. Personal inheritance means “is carried out when it comes to”: the derived class makes use of the bottom internally, exterior code can not convert it to the bottom, and a non-public member object often expresses the identical factor extra clearly. Protected inheritance is uncommon.

The default is the lure. FromClass in this system above was declared class FromClass : Base, with no entry specifier, so it inherits privately: pub continues to be usable inside the category (read_pub() returned 1) however not from exterior. The identical mistake in a separate file:

// default_private_base.cpp - should not compile: `class D : B` inherits
// privately, so B's public members are non-public in D.
class Base {
public:
    int worth = 1;
};

class Derived : Base {};       // no entry specifier: non-public inheritance

int fundamental() {
    Derived d;
    return d.worth;
}
exams/compile-fail/default_private_base.cpp:12:14: error: 'int Base::worth' is inaccessible inside this context
exams/compile-fail/default_private_base.cpp:12:14: error: 'worth' is a non-public member of 'Base'

struct FromStruct : Base inherited publicly, as a result of a struct defaults to public for each members and bases. The way in which encapsulation makes use of non-public and protected inside one class is roofed in encapsulation in C++.

Constructor and Destructor Order

Building goes from the bottom outward; destruction reverses it precisely:

// order.cpp - the order of development and destruction in a category hierarchy.
#embody <iostream>
#embody <string>
#embody <utility>

struct Notice {
    std::string textual content;
    specific Notice(std::string t) : textual content(std::transfer(t)) { std::cout << "  assemble " << textual content << 'n'; }
    ~Notice() { std::cout << "  destroy   " << textual content << 'n'; }
};

struct Base {
    Notice base_member{"Base member"};
    Base() { std::cout << "  Base constructor bodyn"; }
    digital ~Base() { std::cout << "  Base destructor bodyn"; }
};

struct Derived : Base {
    Notice derived_member{"Derived member"};
    Derived() { std::cout << "  Derived constructor bodyn"; }
    ~Derived() override { std::cout << "  Derived destructor bodyn"; }
};

int fundamental() {
    std::cout << "creating:n";
    {
        Derived d;
        std::cout << "destroying:n";
    }
}

Output:

creating:
  assemble Base member
  Base constructor physique
  assemble Derived member
  Derived constructor physique
destroying:
  Derived destructor physique
  destroy   Derived member
  Base destructor physique
  destroy   Base member

The order is fastened by the language, not by the order you write initializers in:

  1. Base courses, within the order they’re listed within the class declaration.
  2. Knowledge members, within the order they’re declared.
  3. The constructor physique.

Destruction runs the destructor physique, then the members in reverse order, then the bases. The sensible consequence: when the Base constructor runs, the Derived half doesn’t exist but, so a digital operate known as from a base constructor runs the bottom model, not the override. Constructors and destructors basically, together with which of them the compiler generates, are in constructors and destructors in C++.

Inheriting Constructors

A derived class that provides habits however no knowledge typically simply forwards its constructors. Since C++11, utilizing Base::Base; does that for each base constructor directly:

// inheriting_ctors.cpp - `utilizing Base::Base;` provides a derived class the bottom
// class's constructors (C++11).
#embody <iostream>
#embody <string>
#embody <utility>

class Connection {
public:
    specific Connection(std::string host, int port = 443)
        : host_(std::transfer(host)), port_(port) {}
    std::string deal with() const { return host_ + ":" + std::to_string(port_); }

non-public:
    std::string host_;
    int port_;
};

class LoggedConnection : public Connection {
public:
    utilizing Connection::Connection;      // each constructor varieties, no boilerplate
    void log() const { std::cout << "related to " << deal with() << 'n'; }
};

int fundamental() {
    LoggedConnection a("instance.com");
    LoggedConnection b("localhost", 8080);
    a.log();
    b.log();
}

Output:

related to instance.com:443
related to localhost:8080

LoggedConnection declares no constructor, but accepted each ("instance.com") and ("localhost", 8080), default argument included. Members the derived class provides are initialized as if by its default constructor: from their default member initializers, or left default-initialized with out one (cppreference). Copy and transfer constructors should not inherited this fashion. So this matches courses like LoggedConnection that add features, not state.

Identify Hiding and the Scope Operator

A member operate in a derived class hides each base-class operate with the identical title, regardless of the parameters. It doesn’t overload them:

// hiding.cpp - a operate in a derived class hides each base-class operate
// with the identical title, no matter their parameters.
#embody <iostream>
#embody <string>

struct Printer {
    void print() const { std::cout << "Printer::print()n"; }
    void print(const std::string& s) const { std::cout << "Printer::print("" << s << "")n"; }
};

struct ColorPrinter : Printer {
    void print(int shade) const { std::cout << "ColorPrinter::print(" << shade << ")n"; }
};

struct FixedPrinter : Printer {
    utilizing Printer::print;              // convey the bottom overloads again
    void print(int shade) const { std::cout << "FixedPrinter::print(" << shade << ")n"; }
};

int fundamental() {
    ColorPrinter c;
    c.print(3);
    c.Printer::print();                // the scope operator reaches the hidden one
    c.Printer::print("draft");

    FixedPrinter f;
    f.print(3);
    f.print();
    f.print("closing");
}

Output:

ColorPrinter::print(3)
Printer::print()
Printer::print("draft")
FixedPrinter::print(3)
Printer::print()
Printer::print("closing")

ColorPrinter declared solely print(int), and that one declaration hid each Printer::print() and Printer::print(const std::string&). The scope operator nonetheless reaches them: c.Printer::print() named the bottom model explicitly. Calling c.print() with out it fails, and Clang’s message factors on the hidden operate:

// hidden_overload.cpp - should not compile: print(int) within the derived class
// hides Printer::print(), so the decision with out arguments finds no match.
struct Printer {
    void print() const {}
};

struct ColorPrinter : Printer {
    void print(int) const {}
};

int fundamental() {
    ColorPrinter c;
    c.print();
}
exams/compile-fail/hidden_overload.cpp:13:12: error: no matching operate for name to 'ColorPrinter::print()'
exams/compile-fail/hidden_overload.cpp:13:7: error: too few arguments to operate name, anticipated 1, have 0; did you imply 'Printer::print'?

FixedPrinter exhibits the repair: utilizing Printer::print; brings the bottom overloads into the derived class’s scope, so all three variations of print are candidates once more and regular overload decision picks one. Neither print right here is digital, so that is hiding, not overriding: which operate runs relies upon solely on the static kind of the article or reference.

Digital Capabilities, override and closing

To let a derived class exchange a base-class operate, so {that a} name by a base reference or pointer runs the derived model, the operate have to be digital:

// final_and_override.cpp - digital features, override and closing.
#embody <iostream>
#embody <reminiscence>
#embody <vector>

class Cost {
public:
    digital ~Cost() = default;
    digital double price(double quantity) const { return quantity * 0.02; }
    digital const char* title() const { return "cost"; }
};

class Card : public Cost {
public:
    double price(double quantity) const override { return 0.30 + quantity * 0.029; }
    const char* title() const override { return "card"; }
};

// closing: no class can derive from BankTransfer.
class BankTransfer closing : public Cost {
public:
    double price(double) const override { return 1.00; }
    const char* title() const closing { return "financial institution switch"; }
};

int fundamental() {
    std::vector<std::unique_ptr<Cost>> strategies;
    strategies.push_back(std::make_unique<Cost>());
    strategies.push_back(std::make_unique<Card>());
    strategies.push_back(std::make_unique<BankTransfer>());

    for (const auto& m : strategies)
        std::cout << m->title() << " price on 100.00: " << m->price(100.0) << 'n';
}

Output:

cost price on 100.00: 2
card price on 100.00: 3.2
financial institution switch price on 100.00: 1

The loop solely is aware of about Cost, and every m->price(100.0) ran the model belonging to the article’s actual kind. Three key phrases do the work:

  • digital within the base class makes the operate overridable and the decision dispatched at run time.
  • override on the derived operate asks the compiler to verify it actually overrides one thing. A mismatch, similar to a lacking const, turns into an error as an alternative of a brand new, unrelated operate that solely a warning (-Woverloaded-virtual) could level out.
  • closing on a operate stops additional overriding; on a category, it stops additional derivation. BankTransfer is closing, so struct Wire : BankTransfer {}; is rejected:
exams/compile-fail/derive_from_final.cpp:8:8: error: can not derive from 'closing' base 'BankTransfer' in derived kind 'Wire'
exams/compile-fail/derive_from_final.cpp:8:15: error: base 'BankTransfer' is marked 'closing'

How digital calls work beneath (the vtable and the hidden vptr in every object), pure digital features and summary courses are lined within the digital features information.

The Digital Destructor Rule

A base class that’s used polymorphically wants a digital destructor. This program deletes one derived object accurately and, when given an argument, one incorrectly:

// virtual_dtor.cpp - deleting a derived object by a base pointer.
// And not using a digital destructor within the base, that is undefined habits.
#embody <iostream>
#embody <reminiscence>
#embody <string>

struct Plain {                         // no digital destructor
    ~Plain() { std::cout << "  ~Plainn"; }
};
struct PlainChild : Plain {
    std::string buffer = std::string(64, 'x');   // owns heap reminiscence
    ~PlainChild() { std::cout << "  ~PlainChildn"; }
};

struct Secure {
    digital ~Secure() { std::cout << "  ~Safen"; }
};
struct SafeChild : Secure {
    std::string buffer = std::string(64, 'x');
    ~SafeChild() override { std::cout << "  ~SafeChildn"; }
};

int fundamental(int argc, char*[]) {
    std::cout << "digital destructor:n";
    { std::unique_ptr<Secure> p = std::make_unique<SafeChild>(); }

    if (argc > 1) {                    // the damaged case runs solely on request
        std::cout << "no digital destructor:n";
        Plain* p = new PlainChild;
        delete p;                      // undefined habits
    }
}

Output (regular run):

digital destructor:
  ~SafeChild
  ~Secure

Via std::unique_ptr<Secure>, each destructors ran, derived first. With the argument, the second case printed solely ~Plain: delete p known as Plain‘s destructor as a result of that’s the static kind, ~PlainChild by no means ran, and its 64-character std::string was by no means freed. This system exited with standing 0 on each compilers. AddressSanitizer caught it, however the two compilers’ builds reported totally different issues (GCC first, then Clang; addresses shortened):

==PID==ERROR: AddressSanitizer: new-delete-type-mismatch on 0x... in thread T0:
  measurement of the allotted kind:   32 bytes;
  measurement of the deallocated kind: 1 bytes.
==PID==ERROR: LeakSanitizer: detected reminiscence leaks
Direct leak of 65 byte(s) in 1 object(s) allotted from:
SUMMARY: AddressSanitizer: 65 byte(s) leaked in 1 allocation(s).

GCC’s report is the exact one: 32 bytes have been allotted as a PlainChild and freed as a 1-byte Plain. Clang’s construct reported the consequence, the string buffer that was by no means launched (64 characters plus the terminator). Neither compiler warned at compile time, as a result of Plain has no digital features. Give Plain a digital operate and each do: GCC with -Wdelete-non-virtual-dtor and Clang with -Wdelete-non-abstract-non-virtual-dtor, each in -Wall.

The rule from the C++ Core Tips (C.35): a base class destructor ought to be both public and digital, or protected and non-virtual. The second type makes delete by a base pointer a compile error as an alternative of undefined habits.

Arrays of Derived Objects Via a Base Pointer

A pointer to a derived object converts to a pointer to its base implicitly, and that conversion compiles for arrays too. Indexing the end result doesn’t do what it seems to:

// array_pitfall.cpp - a pointer to Base should not stroll an array of Derived.
// p[1] steps sizeof(Base) bytes, which isn't the place the second Derived begins.
#embody <iostream>

struct Level {
    int x = 0, y = 0;
};
struct Point3 : Level {
    int z = 0;
};

void print_all(const Level* factors, int n) {
    for (int i = 0; i < n; ++i)
        std::cout << "  (" << factors[i].x << ", " << factors[i].y << ")n";
}

int fundamental() {
    Point3 pts[3];
    for (int i = 0; i < 3; ++i) { pts[i].x = i + 1; pts[i].y = (i + 1) * 10; pts[i].z = -1; }

    std::cout << "sizeof(Level) = " << sizeof(Level) << ", sizeof(Point3) = " << sizeof(Point3) << 'n';
    std::cout << "by Point3 objects:n";
    for (const Point3& p : pts) std::cout << "  (" << p.x << ", " << p.y << ")n";
    std::cout << "by a Level*:n";
    print_all(pts, 3);                 // compiles: Point3* converts to Level*
}

Output:

sizeof(Level) = 8, sizeof(Point3) = 12
by Point3 objects:
  (1, 10)
  (2, 20)
  (3, 30)
by a Level*:
  (1, 10)
  (-1, 2)
  (20, -1)
A Level* can not stroll an array of Point3 Point3 pts[3] in reminiscence (4-byte ints), and what array_pitfall.cpp learn by a Level* As Point3 objects: 12-byte steps pts[0] pts[1] pts[2] 1 x 10 y -1 z 2 x 20 y -1 z 3 x 30 y -1 z p[0] (1, 10) p[1] (-1, 2) p[2] (20, -1) Via a Level*: 8-byte steps the Level a part of every Point3 (x, y) the member Point3 provides (z) p[i] means *(p + i), and p + i strikes i * sizeof(Level) = 8 bytes. The objects are 12 bytes aside, so p[1] begins at pts[0].z. The conversion from Point3* to Level* wants no forged, and neither compiler nor sanitizer reported it. Measured with GCC 13.3 and Clang 18.1.3, x86-64: sizeof(Level) = 8, sizeof(Point3) = 12.
A Level* steps 8 bytes; the Point3 objects are 12 bytes aside. Solely the primary learn lands on a complete object. The second and third straddle two objects, which is why this system printed (-1, 2) and (20, -1), and nothing reported it.

print_all indexes with factors[i], which steps i * sizeof(Level) = 8 bytes, however the Point3 objects are 12 bytes aside. So the second “level” it printed was pts[0].z and pts[1].x, and the third was pts[1].y and pts[1].z. The habits is undefined ([expr.add]/6), each compilers compiled it with no warning, and AddressSanitizer and UndefinedBehaviorSanitizer reported nothing, as a result of each learn stayed contained in the array. Cross a std::span<const Point3> (C++20) or a std::vector<Point3>&, which carry the ingredient kind, or retailer tips that could the bottom in a container if the weather are of various sorts.

Inheritance or Composition?

Public inheritance is a powerful assertion: each Derived is usable as a Base, endlessly. When that isn’t true, a member object often serves higher.

Query Inheritance Composition (a member object)
Relationship is-a: a Supervisor is an Worker has-a: a Automobile has an Engine
Used by a base reference or pointer? Sure, that’s the level No
Reuses implementation Sure, however exposes the bottom’s public interface Sure, and exposes solely what you ahead
Altering the bottom later Impacts each derived class Impacts one member
Typical match A household of sorts dealt with by one interface Reusing a part inside a category

Choose composition while you solely need to reuse code, and reserve public inheritance for sorts that callers will genuinely deal with as the bottom kind. A category that inherits from a number of bases directly is a separate design query; a number of inheritance in C++ covers it, with the diamond drawback and digital base courses.

Key Takeaways

  • Write public explicitly. class D : B inherits privately; the bottom’s public members grew to become inaccessible from exterior.
  • Personal base members keep non-public to the bottom, even from derived courses. Use protected sparingly, or undergo the bottom’s public features.
  • Bases are constructed first and destroyed final. Name a base constructor from the initializer listing when the bottom has no default constructor.
  • A derived operate hides each base operate with the identical title. utilizing Base::f; restores the overloads; Base::f() calls one explicitly.
  • Mark overrides override, and use closing to shut a category or operate.
  • Give a polymorphic base a digital destructor. With out one, the derived destructor by no means ran and this system nonetheless exited with standing 0.
  • By no means index an array of derived objects by a base pointer. The reads have been improper and no device reported them.

Continuously Requested Questions

Conclusion

Inheritance in C++ is one line of syntax and a handful of guidelines that the compiler applies whether or not you keep in mind them or not: the default entry, the development order, hiding, the static kind that delete makes use of, the stride a pointer steps by. A lot of the failures on this web page compiled cleanly, and two of them ran to a standard exit. The habits that forestall them are quick: write public, mark override, make polymorphic destructors digital, and move hierarchies round by reference or pointer to a single object.

The C++ programming tutorials are collected within the C++ part.

Supply Code and Checks

inheritance

All applications on this web page are within the oop/inheritance listing of the MYCPLUS C++ examples repository.

Construct and check:

cmake -S . -B construct -DCMAKE_BUILD_TYPE=Launch
cmake --build construct
bash exams/run_tests.sh g++ c++17
bash exams/sanitizers.sh g++

What the construct checks. On Linux, with GCC and Clang underneath C++17 and C++20, it builds each program with -Wall -Wextra -pedantic -Werror, runs it and compares its output with this web page, and checks that the 5 compile-fail examples are rejected with the anticipated error. A sanitizer job confirms that the applications run with out an AddressSanitizer or UndefinedBehaviorSanitizer report (together with array_pitfall, whose undefined habits the sanitizers don’t detect) and that the lacking digital destructor is reported. A macOS job runs the identical exams with Apple Clang, and a Home windows job builds each program with MSVC at /W4 /WX and compares the output. The plain-run exit standing of the damaged destructor case and the compiler warnings for a polymorphic base have been checked domestically and should not a part of the construct.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments