다음은 오류를 수정하고 실행할 수 있는 코드입니다. 수정된 부분은 주석으로 표시했습니다.
cpp#include <iostream>
#include <memory>
#include <string>
class Beverage {
public:
virtual ~Beverage() = default;
[[nodiscard]] virtual std::string getDescription() const {
return description;
}
[[nodiscard]] virtual double cost() const = 0;
protected:
std::string description = "Unknown Beverage";
};
class CondimentDecorator : public Beverage {
public:
virtual ~CondimentDecorator() = default;
std::string getDescription() const override {
return beverage->getDescription();
}
protected:
std::shared_ptr<Beverage> beverage;
};
class DarkRoast : public Beverage {
public:
DarkRoast() {
description = "Dark Roast Coffee";
}
[[nodiscard]] double cost() const override {
return 0.99;
}
};
class Espresso : public Beverage {
public:
Espresso() {
description = "Espresso";
}
[[nodiscard]] double cost() const override {
return 1.99;
}
};
class Mocha : public CondimentDecorator {
public:
explicit Mocha(std::shared_ptr<Beverage> beverage) : CondimentDecorator(std::move(beverage)) { // 변경된 부분
}
[[nodiscard]] std::string getDescription() const override {
return beverage->getDescription() + ", Mocha";
}
[[nodiscard]] double cost() const override {
return 0.20 + beverage->cost();
}
};
class Whip : public CondimentDecorator {
public:
explicit Whip(std::shared_ptr<Beverage> beverage) : CondimentDecorator(std::move(beverage)) { // 변경된 부분
}
[[nodiscard]] std::string getDescription() const override {
return beverage->getDescription() + ", Whip";
}
[[nodiscard]] double cost() const override {
return 0.10 + beverage->cost();
}
};
int main() {
std::shared_ptr<Beverage> beverage = std::make_shared<Espresso>();
std::cout << beverage->getDescription() << " $" << beverage->cost() << std::endl;
std::shared_ptr<Beverage> beverage2 = std::make_shared<DarkRoast>();
beverage2 = std::make_shared<Mocha>(std::move(beverage2)); // 변경된 부분
beverage2 = std::make_shared<Mocha>(std::move(beverage2)); // 변경된 부분
beverage2 = std::make_shared<Whip>(std::move(beverage2)); // 변경된 부분
std::cout << beverage2->getDescription() << " $" << beverage2->cost() << std::endl;
// std::unique_ptr<Beverage> beverage3 = std::make_unique<HouseBlend>();
// beverage3 = std::make_unique<Soy>(beverage3.get());
// beverage3 = std::make_unique<Mocha>(beverage3.get());
// beverage3 = std::make_unique<Whip>(beverage3.get());
// std::cout << beverage3->getDescription() << " $" << beverage3->cost() << std::endl;
return 0;
}
수정된 부분은 다음과 같습니다.
Beverage
클래스의getDescription
함수와cost
함수에[[nodiscard]]
속성을 추가했습니다. 이렇게 하면 반환 값을 무시하는 것을 방지할 수 있습니다.Mocha
수정된 코드를 아래에 제시하겠습니다.
cpp#include <iostream>
#include <memory>
#include <string>
class Beverage {
public:
virtual ~Beverage() = default;
[[nodiscard]] virtual std::string getDescription() const {
return description;
}
[[nodiscard]] virtual double cost() const = 0;
protected:
std::string description = "Unknown Beverage";
};
class CondimentDecorator : public Beverage {
public:
virtual ~CondimentDecorator() = default;
CondimentDecorator(std::shared_ptr<Beverage> bev) : beverage(std::move(bev)) {}
std::string getDescription() const override {
return beverage->getDescription();
}
protected:
std::shared_ptr<Beverage> beverage;
};
class DarkRoast : public Beverage {
public:
DarkRoast() {
description = "Dark Roast Coffee";
}
[[nodiscard]] double cost() const override {
return 0.99;
}
};
class Espresso : public Beverage {
public:
Espresso() {
description = "Espresso";
}
[[nodiscard]] double cost() const override {
return 1.99;
}
};
class Mocha : public CondimentDecorator {
public:
explicit Mocha(std::shared_ptr<Beverage> beverage) : CondimentDecorator(std::move(beverage)) {}
[[nodiscard]] std::string getDescription() const override {
return beverage->getDescription() + ", Mocha";
}
[[nodiscard]] double cost() const override {
return 0.20 + beverage->cost();
}
};
class Whip : public CondimentDecorator {
public:
explicit Whip(std::shared_ptr<Beverage> beverage) : CondimentDecorator(std::move(beverage)) {}
[[nodiscard]] std::string getDescription() const override {
return beverage->getDescription() + ", Whip";
}
[[nodiscard]] double cost() const override {
return 0.10 + beverage->cost();
}
};
int main() {
std::shared_ptr<Beverage> beverage = std::make_shared<Espresso>();
std::cout << beverage->getDescription() << " $" << beverage->cost() << std::endl;
std::shared_ptr<Beverage> beverage2 = std::make_shared<DarkRoast>();
beverage2 = std::make_shared<Mocha>(std::move(beverage2));
beverage2 = std::make_shared<Mocha>(std::move(beverage2));
beverage2 = std::make_shared<Whip>(std::move(beverage2));
std::cout << beverage2->getDescription() << " $" << beverage2->cost() << std::endl;
return 0;
}
주요 변경점은 다음과 같습니다.
CondimentDecorator
클래스의 생성자를 추가했습니다.getDescription()
함수와beverage
멤버 변수의 접근 지정자를 수정하여 오류를 해결했습니다.Mocha
클래스와Whip
클래스의 생성자를 수정하여 오류를 해결했습니다.override
지정자를 추가하여 가상 함수를 재정의했습니다.
다음은 오류를 수정하고 실행할 수 있는 코드입니다.
arduino#include <iostream>
#include <memory>
#include <string>
class Beverage {
public:
virtual ~Beverage() = default;
[[nodiscard]] virtual std::string getDescription() const {
return description;
}
[[nodiscard]] virtual double cost() const = 0;
protected:
std::string description = "Unknown Beverage";
};
class CondimentDecorator : public Beverage {
public:
virtual ~CondimentDecorator() = default;
explicit CondimentDecorator(std::shared_ptr<Beverage> bev) : beverage(std::move(bev)) {}
[[nodiscard]] std::string getDescription() const override {
return beverage->getDescription();
}
protected:
std::shared_ptr<Beverage> beverage;
};
class DarkRoast : public Beverage {
public:
DarkRoast() {
description = "Dark Roast Coffee";
}
[[nodiscard]] double cost() const override {
return 0.99;
}
};
class Espresso : public Beverage {
public:
Espresso() {
description = "Espresso";
}
[[nodiscard]] double cost() const override {
return 1.99;
}
};
class Mocha : public CondimentDecorator {
public:
explicit Mocha(std::shared_ptr<Beverage> beverage) : CondimentDecorator(std::move(beverage)) {}
[[nodiscard]] std::string getDescription() const override {
return beverage->getDescription() + ", Mocha";
}
[[nodiscard]] double cost() const override {
return 0.20 + beverage->cost();
}
};
class Whip : public CondimentDecorator {
public:
explicit Whip(std::shared_ptr<Beverage> beverage) : CondimentDecorator(std::move(beverage)) {}
[[nodiscard]] std::string getDescription() const override {
return beverage->getDescription() + ", Whip";
}
[[nodiscard]] double cost() const override {
return 0.10 + beverage->cost();
}
};
int main() {
std::shared_ptr<Beverage> beverage = std::make_shared<Espresso>();
std::cout << beverage->getDescription() << " $" << beverage->cost() << std::endl;
std::shared_ptr<Beverage> beverage2 = std::make_shared<DarkRoast>();
beverage2 = std::make_shared<Mocha>(std::move(beverage2));
beverage2 = std::make_shared<Mocha>(std::move(beverage2));
beverage2 = std::make_shared<Whip>(std::move(beverage2));
std::cout << beverage2->getDescription() << " $" << beverage2->cost() << std::endl;
return 0;
}
Clang-Tidy의 오류 메시지를 수정하기 위해, 다음과 같은 변경을 적용했습니다.
virtual
대신override
키워드 사용explicit
키워드 추가[[nodiscard]]
어트리뷰트 추가
아래는 오류를 수정하고 실행 가능한 코드입니다.
arduino#include <iostream>
#include <memory>
#include <string>
class Beverage {
public:
virtual ~Beverage() = default;
[[nodiscard]] virtual std::string getDescription() const {
return description;
}
[[nodiscard]] virtual double cost() const = 0;
protected:
std::string description = "Unknown Beverage";
};
class CondimentDecorator : public Beverage {
public:
virtual ~CondimentDecorator() = default;
explicit CondimentDecorator(std::shared_ptr<Beverage> bev) : beverage(std::move(bev)) {}
[[nodiscard]] std::string getDescription() const override {
return beverage->getDescription();
}
protected:
std::shared_ptr<Beverage> beverage;
};
class DarkRoast : public Beverage {
public:
DarkRoast() {
description = "Dark Roast Coffee";
}
[[nodiscard]] double cost() const override {
return 0.99;
}
};
class Espresso : public Beverage {
public:
Espresso() {
description = "Espresso";
}
[[nodiscard]] double cost() const override {
return 1.99;
}
};
class Mocha : public CondimentDecorator {
public:
explicit Mocha(std::shared_ptr<Beverage> beverage) : CondimentDecorator(std::move(beverage)) {}
[[nodiscard]] std::string getDescription() const override {
return beverage->getDescription() + ", Mocha";
}
[[nodiscard]] double cost() const override {
return 0.20 + beverage->cost();
}
};
class Whip : public CondimentDecorator {
public:
explicit Whip(std::shared_ptr<Beverage> beverage) : CondimentDecorator(std::move(beverage)) {}
[[nodiscard]] std::string getDescription() const override {
return beverage->getDescription() + ", Whip";
}
[[nodiscard]] double cost() const override {
return 0.10 + beverage->cost();
}
};
int main() {
std::shared_ptr<Beverage> beverage = std::make_shared<Espresso>();
std::cout << beverage->getDescription() << " $" << beverage->cost() << std::endl;
std::shared_ptr<Beverage> beverage2 = std::make_shared<DarkRoast>();
beverage2 = std::make_shared<Mocha>(std::move(beverage2));
beverage2 = std::make_shared<Mocha>(std::move(beverage2));
beverage2 = std::make_shared<Whip>(std::move(beverage2));
std::cout << beverage2->getDescription() << " $" << beverage2->cost() << std::endl;
return 0;
}
위 코드에서 Clang-Tidy가 보고한 오류는 가상 함수를 선언할 때 override 키워드를 사용하지 않았다는 것입니다. 따라서 가상 함수를 오버라이딩할 때는 override 키워드를 사용해야 합니다. 코드에서는 getDescription() 및 cost() 함수를 오버라이딩하고 있으므로, 각 함수 앞에 override 키워드를 추가하여 오류를 수정했습니다.
// 이 코드는 데코레이터 패턴을 사용하여 커피음료에 토핑을 추가하는 예시를 보여줍니다. #include <iostream> #include <memory> #include <string>
// Beverage 클래스는 음료 추상화 클래스입니다. class Beverage { public: // 가상 소멸자 virtual ~Beverage() = default;
csharp// getDescription() 함수는 음료 이름을 반환합니다.
[[nodiscard]] virtual std::string getDescription() const {
return description;
}
// cost() 함수는 음료 가격을 반환합니다.
[[nodiscard]] virtual double cost() const = 0;
protected: std::string description = "Unknown Beverage"; };
// CondimentDecorator 클래스는 데코레이터 추상화 클래스입니다. class CondimentDecorator : public Beverage { public: // 가상 소멸자 ~CondimentDecorator() override = default;
c// 음료 객체를 포함하는 생성자
explicit CondimentDecorator(std::shared_ptr<Beverage> bev) : beverage(std::move(bev)) {}
// getDescription() 함수는 감싸고 있는 음료 객체의 이름을 반환합니다.
[[nodiscard]] std::string getDescription() const override {
return beverage->getDescription();
}
protected: std::shared_ptr<Beverage> beverage; };
// DarkRoast 클래스는 음료 클래스를 상속하며, 이름과 가격을 설정합니다. class DarkRoast : public Beverage { public: DarkRoast() { description = "Dark Roast Coffee"; }
csharp[[nodiscard]] double cost() const override {
return 0.99;
}
};
// Espresso 클래스는 음료 클래스를 상속하며, 이름과 가격을 설정합니다. class Espresso : public Beverage { public: Espresso() { description = "Espresso"; }
csharp[[nodiscard]] double cost() const override {
return 1.99;
}
};
// Mocha 클래스는 데코레이터 추상화 클래스를 상속하며, Mocha 토핑의 가격과 이름을 설정합니다. class Mocha : public CondimentDecorator { public: explicit Mocha(std::shared_ptr<Beverage> beverage) : CondimentDecorator(std::move(beverage)) {}
lua[[nodiscard]] std::string getDescription() const override {
return beverage->getDescription() + ", Mocha";
}
[[nodiscard]] double cost() const override {
return 0.20 + beverage->cost();
}
};
// Whip 클래스는 데코레이터 추상화 클래스를 상속하며, Whip 토핑의 가격과 이름을 설정합니다. class Whip : public CondimentDecorator { public: explicit Whip(std::shared_ptr<Beverage> beverage) : CondimentDecorator(std::move(beverage)) {}
lua[[nodiscard]] std::string getDescription() const override {
return beverage->getDescription() + ", Whip";
}
[[nodiscard]] double cost() const override {
return 0.10 + beverage->cost();
}
};
int main() { // Espresso 객체 생성 std::shared_ptr<Beverage> beverage = std::make_shared<Espresso>(); std::cout << beverage->getDescription() << " $" << beverage->cost() << std::endl;
arduino// DarkRoast 객체 생성 후 Mocha, Mocha, Whip 토
여기에 main() 함수를 추가해 보겠습니다.
cpp#include <iostream>
#include <memory>
#include <string>
class Beverage {
public:
virtual ~Beverage() = default;
[[nodiscard]] virtual std::string getDescription() const {
return description;
}
[[nodiscard]] virtual double cost() const = 0;
protected:
std::string description = "Unknown Beverage";
};
class CondimentDecorator : public Beverage {
public:
~CondimentDecorator() override = default;
explicit CondimentDecorator(std::shared_ptr<Beverage> bev) : beverage(std::move(bev)) {}
[[nodiscard]] std::string getDescription() const override {
return beverage->getDescription();
}
protected:
std::shared_ptr<Beverage> beverage;
};
class DarkRoast : public Beverage {
public:
DarkRoast() {
description = "Dark Roast Coffee";
}
[[nodiscard]] double cost() const override {
return 0.99;
}
};
class Espresso : public Beverage {
public:
Espresso() {
description = "Espresso";
}
[[nodiscard]] double cost() const override {
return 1.99;
}
};
class Mocha : public CondimentDecorator {
public:
explicit Mocha(std::shared_ptr<Beverage> beverage) : CondimentDecorator(std::move(beverage)) {}
[[nodiscard]] std::string getDescription() const override {
return beverage->getDescription() + ", Mocha";
}
[[nodiscard]] double cost() const override {
return 0.20 + beverage->cost();
}
};
class Whip : public CondimentDecorator {
public:
explicit Whip(std::shared_ptr<Beverage> beverage) : CondimentDecorator(std::move(beverage)) {}
[[nodiscard]] std::string getDescription() const override {
return beverage->getDescription() + ", Whip";
}
[[nodiscard]] double cost() const override {
return 0.10 + beverage->cost();
}
};
int main() {
// 첫 번째 음료: 에스프레소
std::shared_ptr<Beverage> beverage = std::make_shared<Espresso>();
std::cout << beverage->getDescription() << " $" << beverage->cost() << std::endl;
// 두 번째 음료: 다크 로스트에 모카 2개와 휘핑 추가
std::shared_ptr<Beverage> beverage2 = std::make_shared<DarkRoast>();
beverage2 = std::make_shared<Mocha>(std::move(beverage2));
beverage2 = std::make_shared<Mocha>(std::move(beverage2));
beverage2 = std::make_shared<Whip>(std::move(beverage2));
std::cout << beverage2->getDescription() << " $" << beverage2->cost() << std::endl;
return 0;
}
[[nodiscard]]는 C++11에서 추가된 언어 기능 중 하나로, 함수나 메서드의 반환 값이 사용되지 않을 경우 경고 메시지를 출력하도록 지정하는 역할을 합니다.
이 기능을 사용하면 컴파일러가 경고를 출력하여 프로그래머가 함수의 반환 값을 무시하는 실수를 방지할 수 있습니다. 이를 통해 코드의 안정성을 높이고 디버깅을 용이하게 할 수 있습니다.
즉, 해당 함수나 메서드가 반환하는 값이 중요하고 그 값을 무시하면 문제가 발생할 수 있는 경우에는 [[nodiscard]]를 사용해야 합니다. 그러나 값이 무시되어도 문제가 발생하지 않는 경우에는 굳이 [[nodiscard]]를 사용하지 않아도 됩니다.
위의 코드에서 [[nodiscard]]는 함수가 반환하는 값이 사용되지 않을 경우 경고 메시지를 출력하도록 지정해준 것입니다. Beverage 클래스에서 getDescription()과 cost() 메서드, 그리고 Mocha와 Whip 클래스에서 getDescription()과 cost() 메서드에 [[nodiscard]]를 사용했습니다. 이는 해당 메서드들이 반환하는 값이 중요하고 무시되면 문제가 발생할 수 있기 때문입니다.