첫 번째로, 즉각적인 문제는 거의 확실합니다. ~Fruit()
은 virtual
이 아닙니다. 그것을 (virtual ~Fruit() = default
또는 virtual ~Fruit() {}
에서 class Fruit
까지) 추가하면 게시 된 코드가 마술처럼 작동하기 시작할 것입니다.
그러나 이는 사용자 코드가 아닐 수 있습니다. 그냥 노력하고 있습니다. 음.
코드를 개선 할 수있는 부분이 많이 있습니다. 첫 번째 개선으로 우리는 unique_ptr
를 사용합니다 : (@Deduplicator 댓글에 위에서 언급 한 바와 같이) 리스너의 수명이 묶여 있도록 RAII를 사용
int32_t Fruit::frutificate(const Settings& settings) {
std::unique_ptr<Fruit> listener;
if (settings.has_domain_socket()) {
listener.reset(new Apple(settings));
} else {
listener.reset(new Orange(settings));
}
int r = uv_run(listener->loop, UV_RUN_DEFAULT);
return r;
}
합니다. 훨씬 더 좋고, 더 이상 수동 인 delete
(우연히 또는 예외로 놓칠 수 있음). C에서
14 ++의 .reset(new Blah(whatever))
는 = std::make_unique<Blah>(whatever);
로 대체 할 수 있으며, 지금 당신의 코드는 결코 명시 적으로 얻을 수있는 좋은 습관이다, new
및 delete
호출합니다. 그러나 귀하의 코드는 C++ 11 태그이므로 위의 C++ 11 버전을 그대로 두겠습니다.
더 좋을지라도 최선을 다할 수 있습니다. 무료 저장소 (힙)를 전혀 사용할 필요가 없습니다.
무료 저장 사용을 방지하는 간단한 방법은 다음과 같습니다 uv_run
코드를 반복 단점이있다 (따라서 버그를 낳을 수)
int32_t Fruit::frutificate(const Settings& settings) {
if (settings.has_domain_socket()) {
return uv_run(Apple(settings).loop, UV_RUN_DEFAULT);
} else {
return uv_run(Orange(settings).loop, UV_RUN_DEFAULT);
}
}
(위의 의견에 @Jarod에서 도난). 우리는 람다와 함께이 문제를 해결할 수 있습니다 : 우리는 다음 람다에 공통 코드를 고려하고,
int32_t Fruit::frutificate(const Settings& settings) {
auto fruit_the_uv = [&](Fruit&& fruit) {
return uv_run(fruit.loop, UV_RUN_DEFAULT);
};
if (settings.has_domain_socket()) {
return fruit_the_uv(Apple(settings));
} else {
return fruit_the_uv(Orange(settings));
}
}
두 가지에를 호출합니다. 우리가 임시 과일을 전달할 때 rvalue reference를 사용했습니다.
플러스 fruit_the_uv
은 읽을 때마다 90srap song을 상기시킵니다. 그리고 그것은 더하기입니다.
'과일'에 가상 소멸자가 있습니까? 그렇지 않으면 정의되지 않은 동작이 발생합니다 (그렇지 않으면 올바른 소멸자를 호출하지 못했음을 나타냄). –
@lapinrigolo 보여주는 코드는 인스턴스를 구성하고 파기하는 측면에서 정확합니다. 'listener.loop'를'listener-> loop'로 바꿔야 할 수도 있습니다. – quamrana
또한'std :: unique_ptr'을 사용해야합니다. 'uv_run'이'noexcept'인지는 중요하지 않습니다. – Deduplicator