Почему статические классы не могут иметь деструкторов?

Можно решить проблему без копирования всех std::strings, пока функция не изменяет переданную в char**. В противном случае я не вижу альтернативы, кроме как скопировать все в новую структуру char ** ` (см. Второй пример) .

void old_func(char** carray, size_t size)
{
    for(size_t i = 0; i < size; ++i)
        std::cout << carray[i] << '\n';
}

int main()
{
    std::vector<std::string> strings {"one", "two", "three"};
    std::vector<char*> cstrings;
    cstrings.reserve(strings.size());

    for(size_t i = 0; i < strings.size(); ++i)
        cstrings.push_back(const_cast<char*>(strings[i].c_str()));

    // Do not change any of the strings here as that will
    // invalidate the new data structure that relies on
    // the returned values from `c_str()`
    //
    // This is not an issue after C++11 as long as you don't
    // increase the length of a string (as that may cause reallocation)

    if(!cstrings.empty())
        old_func(&cstrings[0], cstrings.size());
}

ПРИМЕР 2: Если функция должна изменить переданные в данных:

void old_func(char** carray, size_t size)
{
    for(size_t i = 0; i < size; ++i)
        std::cout << carray[i] << '\n';
}

int main()
{
    {
        // pre C++11
        std::vector<std::string> strings {"one", "two", "three"};

        // guarantee contiguous, null terminated strings
        std::vector<std::vector<char>> vstrings;

        // pointers to rhose strings
        std::vector<char*> cstrings;

        vstrings.reserve(strings.size());
        cstrings.reserve(strings.size());

        for(size_t i = 0; i < strings.size(); ++i)
        {
            vstrings.emplace_back(strings[i].begin(), strings[i].end());
            vstrings.back().push_back('\0');
            cstrings.push_back(vstrings.back().data());
        }

        old_func(cstrings.data(), cstrings.size());
    }

    {
        // post C++11
        std::vector<std::string> strings {"one", "two", "three"};

        std::vector<char*> cstrings;   
        cstrings.reserve(strings.size());

        for(auto& s: strings)
            cstrings.push_back(&s[0]);

        old_func(cstrings.data(), cstrings.size());
    }
}

ПРИМЕЧАНИЕ: пересмотрен для обеспечения лучшего кода.

13
задан Konamiman 15 June 2015 в 19:30
поделиться

4 ответа

Вместо статического класса вы должны использовать обычный класс с одноэлементным шаблоном (то есть вы сохраняете один единственный экземпляр класса, на который, возможно, ссылается одно статическое свойство в самом классе) . Затем у вас может быть деструктор или, что еще лучше, комбинация деструктора и метода Dispose .

Например, если теперь у вас есть:

static class MyClass
{
    public static void MyMethod() {...}
}

//Using the class:
MyClass.MyMethod();

, вместо этого вы получите:

class MyClass : IDisposable
{
    public static MyClass()
    {
        Instance=new MyClass();
    }

    public static MyClass Instance {get; private set;}

    public void MyMethod() {...}

    public void Dispose()
    {
        //...
    }

    ~MyClass()
    {
        //Your destructor goes here
    }
}

//Using the class:
MyClass.Instance.MyMethod();

(Обратите внимание, как экземпляр создается в статическом конструкторе, который вызывается при первом обращении к любому из статических членов класса)

19
ответ дан 1 December 2019 в 20:29
поделиться
  1. Статические классы не имеют деструкторов, потому что статический класс никогда не уничтожается.

  2. Если вы хотите создать и уничтожить несколько его экземпляров, он не должен быть статическим. Сделайте его полным классом.

  3. Деструкторы в любом случае использовать для этой цели не следует. Используйте IDisposable / Dispose.

7
ответ дан 1 December 2019 в 20:29
поделиться

1. Почему? - Тип не может иметь конструктора как такового, как в обычном понимании конструкторов экземпляров. В общем, его иногда называют методом «статического инициализатора», но Microsoft использует терминологию «конструктор типа» (и у него есть особые ограничения) - вы помещаете в него код для инициализации типа / класса - если это был конструктор экземпляра, он мог бы быть перегружен. Это статическое ограничение для «конструктора типов» связано с тем, что .NET CLR отвечает за загрузку шаблона класса в куче и не позволяет указывать параметры в этом случае (потому что как бы вы могли передавать аргументы). Поскольку в самом строгом смысле программист не несет ответственности за вызов конструктора типа, не имеет большого смысла позволять программисту кодировать статический деструктор, когда он находится в домене CLR. В конечном итоге среда CLR удалит шаблон класса из кучи, но время жизни шаблона класса больше, чем у его экземпляров, поэтому вы все равно не захотите делать в нем что-либо ресурсоемкое (например, удерживать соединение с базой данных).

2 . Какой? - Синглтон В любом случае я не хочу делать в нем что-либо ресурсоемкое (например, держать открытым соединение с базой данных).

2. Какой? - Синглтон В любом случае я не хочу делать в нем что-либо ресурсоемкое (например, держать открытым соединение с базой данных).

2. Какой? - Синглтон Если вы столкнулись с ситуацией, когда вам кажется, что вам нужно открыть ресурс в шаблоне класса и затем уничтожить его, вы можете подумать, что программный шаблон Singleton имеет только один экземпляр этого класса и, возможно, также реализует интерфейс System.IDiposable для помощи в очистке в дополнение к деструктору. (Я вижу, что кто-то уже опередил меня по образцу кода IDisposable, поэтому на этом я закончу свое решение.)

3
ответ дан 1 December 2019 в 20:29
поделиться

Статический класс никогда не уничтожается. Завершается вместе с программой. Вы можете использовать шаблон singleton в качестве реализации вместо использования статического класса

1
ответ дан 1 December 2019 в 20:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: