У меня есть класс Bar
, в котором есть член типа Foo
.Класс Foo
должен создаваться только в определенных фиксированных и постоянных состояниях, которые различаются на основе Tag
.Поскольку я не хочу, чтобы Foo
создавался в каком-либо другом состоянии, я сделал его конструктор закрытым и реализовал фабрику FooFactory
.
. В списке инициализатора конструктора Bar
я вызываюфункция make_Foo
, которая возвращает правильный экземпляр Foo
на основе Tag
.
#include <stdexcept>
#include <string>
#include <iostream>
enum class Tag
{
A,
B,
C
};
class Foo
{
public:
friend class FooFactory;
const Tag tag;
const std::string string;
private:
Foo(Tag tag, std::string string):
tag {tag}, string {string}
{};
};
class FooFactory
{
public:
static Foo A()
{
return Foo(Tag::A, {"This is string A"});
}
static Foo B()
{
return Foo(Tag::B, {"This is string A"});
}
};
Foo make_Foo(Tag tag)
{
switch(tag)
{
case Tag::A: return FooFactory::A();
case Tag::B: return FooFactory::B();
default: throw std::runtime_error("Called with invalid Tag.");
}
}
class Bar
{
public:
std::string another_string;
const Foo foo;
Bar(Tag tag, std::string another_string):
another_string {another_string}, foo {make_Foo(tag)}
{};
};
int main()
{
Tag tag = Tag::C;
Bar bar(tag, "This is a string");
std::cout << "bar constructed" << std::endl;
}
Я хочу, чтобы генерировалось исключение, когда Foo
создается с Tag::C
, чтоне реализованы.Приведенный выше код вызывает это исключение, но Вальгринд Мемчек говорит, что в этом случае происходит утечка памяти.
При дальнейшем исследовании я вижу, что, хотя bar.foo
не создается на заводе при пропуске Tag::C
, bar.foo
все еще инициализируется с неизвестным Tag
и пустым std::string
.Это память, которая просочилась в этом случае?Как я могу избежать этого при возникновении исключения?
пс.В действительности Foo
является нетиповым классом шаблона, а для Tag::C
используется другой параметр шаблона.Вот почему мне нужна диспетчеризация тегов.