An abstract class declares an interface that derived classes must implement.

pure virtual A pure virtual function, written with `= 0`, makes a class abstract.

Abstract Classes

example
abstract_classes.cpp
Replay: real traced execution (multi-file project)
#include <iostream>
#include <string>

class Task {
public:
    virtual std::string label() = 0;
    virtual int effort() = 0;
};

class EmailTask : public Task {
private:
    int messages;

public:
    EmailTask(int count) {
        messages = count;
    }

    std::string label() override {
        return "email";
    }

    int effort() override {
        return messages * 2;
    }
};

class BuildTask : public Task {
private:
    int files;

public:
    BuildTask(int count) {
        files = count;
    }

    std::string label() override {
        return "build";
    }

    int effort() override {
        return files * 3;
    }
};

int main() {
    bool useBuild = false;
    int count = 3;

    EmailTask email(count);
    BuildTask build(count);
    Task* task = &email;

    if (useBuild) {
        task = &build;
    }

    std::cout << "task=" << task->label() << std::endl;
    std::cout << "effort=" << task->effort() << std::endl;
    return 0;
}
#include <iostream>
#include <string>

class Task {
public:
    virtual std::string label() = 0;
    virtual int effort() = 0;
};

class EmailTask : public Task {
private:
    int messages;

public:
    EmailTask(int count) {
        messages = count;
    }

    std::string label() override {
        return "email";
    }

    int effort() override {
        return messages * 2;
    }
};

class BuildTask : public Task {
private:
    int files;

public:
    BuildTask(int count) {
        files = count;
    }

    std::string label() override {
        return "build";
    }

    int effort() override {
        return files * 3;
    }
};

int main() {
    bool useBuild = true;
    int count = 3;

    EmailTask email(count);
    BuildTask build(count);
    Task* task = &email;

    if (useBuild) {
        task = &build;
    }

    std::cout << "task=" << task->label() << std::endl;
    std::cout << "effort=" << task->effort() << std::endl;
    return 0;
}
#include <iostream>
#include <string>

class Task {
public:
    virtual std::string label() = 0;
    virtual int effort() = 0;
};

class EmailTask : public Task {
private:
    int messages;

public:
    EmailTask(int count) {
        messages = count;
    }

    std::string label() override {
        return "email";
    }

    int effort() override {
        return messages * 2;
    }
};

class BuildTask : public Task {
private:
    int files;

public:
    BuildTask(int count) {
        files = count;
    }

    std::string label() override {
        return "build";
    }

    int effort() override {
        return files * 3;
    }
};

int main() {
    bool useBuild = false;
    int count = 1;

    EmailTask email(count);
    BuildTask build(count);
    Task* task = &email;

    if (useBuild) {
        task = &build;
    }

    std::cout << "task=" << task->label() << std::endl;
    std::cout << "effort=" << task->effort() << std::endl;
    return 0;
}
#include <iostream>
#include <string>

class Task {
public:
    virtual std::string label() = 0;
    virtual int effort() = 0;
};

class EmailTask : public Task {
private:
    int messages;

public:
    EmailTask(int count) {
        messages = count;
    }

    std::string label() override {
        return "email";
    }

    int effort() override {
        return messages * 2;
    }
};

class BuildTask : public Task {
private:
    int files;

public:
    BuildTask(int count) {
        files = count;
    }

    std::string label() override {
        return "build";
    }

    int effort() override {
        return files * 3;
    }
};

int main() {
    bool useBuild = false;
    int count = 5;

    EmailTask email(count);
    BuildTask build(count);
    Task* task = &email;

    if (useBuild) {
        task = &build;
    }

    std::cout << "task=" << task->label() << std::endl;
    std::cout << "effort=" << task->effort() << std::endl;
    return 0;
}
  1. useBuild ← 0, count ← 3

    46int main() {47    bool useBuild→ 0 = false; //@useBuild=true48    int count→ 3 = 3; //@count=1, 54950    EmailTask email(count3);51    BuildTask build(count);
  2. messages ← 3

    14public:15    EmailTask(int count3) {16        messages→ 3 = count3;17    }
  3. email ← (empty)

    50EmailTask email→ (empty)(count3);51BuildTask build(count3);52Task* task = &email;
  4. files ← 3

    32public:33    BuildTask(int count3) {34        files→ 3 = count3;35    }
  5. build ← (empty), task ← ⟨addr A⟩

    50EmailTask email(count);51BuildTask build→ (empty)(count3);52Task* task→ ⟨addr A⟩ = &email(empty);5354if (useBuild) {55    task = &build;56}5758std::cout << "task=" << task⟨addr A⟩->label() << std::endl;59std::cout << "effort=" << task->effort() << std::endl;
  6. std::cout << "task=" << task->label() << std::endl;

    58std::cout << "task=" << task⟨addr A⟩->label() << std::endl;59std::cout << "effort=" << task⟨addr A⟩->effort() << std::endl;60return 0;
    outputtask=email
  7. int effort() override

    23int effort() override {24    return messages3 * 2;25}
  8. std::cout << "effort=" << task->effort() << std::endl;

    58    std::cout << "task=" << task->label() << std::endl;59    std::cout << "effort=" << task⟨addr A⟩->effort() << std::endl;60    return 0;61}
    outputeffort=6
  1. useBuild ← 1, count ← 3

    46int main() {47    bool useBuild→ 1 = true;48    int count→ 3 = 3;4950    EmailTask email(count3);51    BuildTask build(count);
  2. messages ← 3

    14public:15    EmailTask(int count3) {16        messages→ 3 = count3;17    }
  3. email ← (empty)

    50EmailTask email→ (empty)(count3);51BuildTask build(count3);52Task* task = &email;
  4. files ← 3

    32public:33    BuildTask(int count3) {34        files→ 3 = count3;35    }
  5. build ← (empty), task ← ⟨addr A⟩

    50EmailTask email(count);51BuildTask build→ (empty)(count3);52Task* task→ ⟨addr A⟩ = &email(empty);
  6. task ← ⟨addr B⟩

    54if (useBuild1) {55    task→ ⟨addr B⟩ = &build(empty);56}
  7. std::cout << "task=" << task->label() << std::endl;

    58std::cout << "task=" << task⟨addr B⟩->label() << std::endl;59std::cout << "effort=" << task->effort() << std::endl;
  8. std::cout << "task=" << task->label() << std::endl;

    58std::cout << "task=" << task⟨addr B⟩->label() << std::endl;59std::cout << "effort=" << task⟨addr B⟩->effort() << std::endl;60return 0;
    outputtask=build
  9. int effort() override

    41int effort() override {42    return files3 * 3;43}
  10. std::cout << "effort=" << task->effort() << std::endl;

    58    std::cout << "task=" << task->label() << std::endl;59    std::cout << "effort=" << task⟨addr B⟩->effort() << std::endl;60    return 0;61}
    outputeffort=9
  1. useBuild ← 0, count ← 1

    46int main() {47    bool useBuild→ 0 = false;48    int count→ 1 = 1;4950    EmailTask email(count1);51    BuildTask build(count);
  2. messages ← 1

    14public:15    EmailTask(int count1) {16        messages→ 1 = count1;17    }
  3. email ← (empty)

    50EmailTask email→ (empty)(count1);51BuildTask build(count1);52Task* task = &email;
  4. files ← 1

    32public:33    BuildTask(int count1) {34        files→ 1 = count1;35    }
  5. build ← (empty), task ← ⟨addr A⟩

    50EmailTask email(count);51BuildTask build→ (empty)(count1);52Task* task→ ⟨addr A⟩ = &email(empty);5354if (useBuild) {55    task = &build;56}5758std::cout << "task=" << task⟨addr A⟩->label() << std::endl;59std::cout << "effort=" << task->effort() << std::endl;
  6. std::cout << "task=" << task->label() << std::endl;

    58std::cout << "task=" << task⟨addr A⟩->label() << std::endl;59std::cout << "effort=" << task⟨addr A⟩->effort() << std::endl;60return 0;
    outputtask=email
  7. int effort() override

    23int effort() override {24    return messages1 * 2;25}
  8. std::cout << "effort=" << task->effort() << std::endl;

    58    std::cout << "task=" << task->label() << std::endl;59    std::cout << "effort=" << task⟨addr A⟩->effort() << std::endl;60    return 0;61}
    outputeffort=2
  1. useBuild ← 0, count ← 5

    46int main() {47    bool useBuild→ 0 = false;48    int count→ 5 = 5;4950    EmailTask email(count5);51    BuildTask build(count);
  2. messages ← 5

    14public:15    EmailTask(int count5) {16        messages→ 5 = count5;17    }
  3. email ← (empty)

    50EmailTask email→ (empty)(count5);51BuildTask build(count5);52Task* task = &email;
  4. files ← 5

    32public:33    BuildTask(int count5) {34        files→ 5 = count5;35    }
  5. build ← (empty), task ← ⟨addr A⟩

    50EmailTask email(count);51BuildTask build→ (empty)(count5);52Task* task→ ⟨addr A⟩ = &email(empty);5354if (useBuild) {55    task = &build;56}5758std::cout << "task=" << task⟨addr A⟩->label() << std::endl;59std::cout << "effort=" << task->effort() << std::endl;
  6. std::cout << "task=" << task->label() << std::endl;

    58std::cout << "task=" << task⟨addr A⟩->label() << std::endl;59std::cout << "effort=" << task⟨addr A⟩->effort() << std::endl;60return 0;
    outputtask=email
  7. int effort() override

    23int effort() override {24    return messages5 * 2;25}
  8. std::cout << "effort=" << task->effort() << std::endl;

    58    std::cout << "task=" << task->label() << std::endl;59    std::cout << "effort=" << task⟨addr A⟩->effort() << std::endl;60    return 0;61}
    outputeffort=10