Когда у меня была та же проблема, я остановил свой сервер mongo и снова начал его с помощью команды
mongod --repair
Перед запуском операции восстановления вы должны проверить, достаточно ли свободного места на вашем жестком диске (мин - размер вашей базы данных)
Вот сводка по static_cast<>
и dynamic_cast<>
, в частности, по указателям. Это просто обзор 101 уровня, он не охватывает всех тонкостей.
Здесь берется указатель в ptr
и делается попытка безопасно привести его к указателю типа Type*
. Приведение выполняется во время компиляции. Приведение будет выполнено только в том случае, если типы связаны. Если типы не связаны, вы получите ошибку компилятора. Например:
class B {};
class D : public B {};
class X {};
int main()
{
D* d = new D;
B* b = static_cast<B*>(d); // this works
X* x = static_cast<X*>(d); // ERROR - Won't compile
return 0;
}
Это снова попытка взять указатель в ptr
и безопасно привести его к указателю типа Type*
. Но это приведение выполняется во время выполнения, а не во время компиляции. Поскольку это приведение выполняется во время выполнения, оно полезно, особенно в сочетании с полиморфными классами. Фактически, в некоторых случаях классы должны быть полиморфными, чтобы приведение было законным.
Приведение может происходить в одном из двух направлений: от базового к производному (B2D) или от производного к базовому (D2B). Достаточно просто увидеть, как касты D2B будут работать во время выполнения. Либо ptr
является производным от Type
, либо нет. В случае с D2B dynamic_cast<>s правила просты. Вы можете попытаться привести что угодно к чему угодно другому, и если ptr
действительно был производным от Type
, вы получите указатель Type*
обратно от dynamic_cast
. В противном случае вы получите указатель NULL.
Но касты B2D немного сложнее. Рассмотрим следующий код:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void DoIt() = 0; // pure virtual
virtual ~Base() {};
};
class Foo : public Base
{
public:
virtual void DoIt() { cout << "Foo"; };
void FooIt() { cout << "Fooing It..."; }
};
class Bar : public Base
{
public :
virtual void DoIt() { cout << "Bar"; }
void BarIt() { cout << "baring It..."; }
};
Base* CreateRandom()
{
if( (rand()%2) == 0 )
return new Foo;
else
return new Bar;
}
int main()
{
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();
base->DoIt();
Bar* bar = (Bar*)base;
bar->BarIt();
}
return 0;
}
main()
не может сказать, какой объект вернет CreateRandom()
, поэтому приведение в стиле C Bar* bar = (Bar*)base;
явно не безопасно для типов. Как это можно исправить? Один из способов - добавить в базовый класс функцию типа bool AreYouABar() const = 0;
и возвращать true
из Bar
и false
из Foo
. Но есть и другой способ: используйте dynamic_cast<>
:
int main()
{
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();
base->DoIt();
Bar* bar = dynamic_cast<Bar*>(base);
Foo* foo = dynamic_cast<Foo*>(base);
if( bar )
bar->BarIt();
if( foo )
foo->FooIt();
}
return 0;
}
Приведение выполняется во время выполнения и работает путем запроса объекта (пока не нужно беспокоиться о том, как), спрашивая его, тот ли это тип, который мы ищем. Если да, то dynamic_cast
возвращает указатель; в противном случае возвращается NULL.
Для того, чтобы это приведение от базового типа к производному работало с использованием dynamic_cast<>
, Base, Foo и Bar должны быть тем, что в стандарте называется полиморфными типами. Чтобы быть полиморфным типом, ваш класс должен иметь хотя бы одну виртуальную
функцию. Если ваши классы не являются полиморфными типами, то использование dynamic_cast
не будет компилироваться. Пример:
class Base {};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // ERROR - Won't compile
return 0;
}
Добавление виртуальной функции к base, например, виртуального dtor, сделает и Base, и Der полиморфными типами:
class Base
{
public:
virtual ~Base(){};
};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // OK
return 0;
}
Нижеследующее не совсем близко к тому, что вы получаете от dynamic_cast
C ++ с точки зрения проверки типов, но, возможно, это поможет вам понять его цель немного лучше:
struct Animal // Would be a base class in C++
{
enum Type { Dog, Cat };
Type type;
};
Animal * make_dog()
{
Animal * dog = new Animal;
dog->type = Animal::Dog;
return dog;
}
Animal * make_cat()
{
Animal * cat = new Animal;
cat->type = Animal::Cat;
return cat;
}
Animal * dyn_cast(AnimalType type, Animal * animal)
{
if(animal->type == type)
return animal;
return 0;
}
void bark(Animal * dog)
{
assert(dog->type == Animal::Dog);
// make "dog" bark
}
int main()
{
Animal * animal;
if(rand() % 2)
animal = make_dog();
else
animal = make_cat();
// At this point we have no idea what kind of animal we have
// so we use dyn_cast to see if it's a dog
if(dyn_cast(Animal::Dog, animal))
{
bark(animal); // we are sure the call is safe
}
delete animal;
}
Больше, чем код на C, я думаю, что определение на английском языке могло бы достаточно:
Учитывая класс Base, от которого существует производный класс Derived, dynamic_cast
преобразует указатель Base в указатель Derived тогда и только тогда, когда фактический объект, на который указывает, на самом деле является производным объектом .
class Base { virtual ~Base() {} };
class Derived : public Base {};
class Derived2 : public Base {};
class ReDerived : public Derived {};
void test( Base & base )
{
dynamic_cast<Derived&>(base);
}
int main() {
Base b;
Derived d;
Derived2 d2;
ReDerived rd;
test( b ); // throw: b is not a Derived object
test( d ); // ok
test( d2 ); // throw: d2 is not a Derived object
test( rd ); // ok: rd is a ReDerived, and thus a derived object
}
В этом примере вызов test
связывает различные объекты со ссылкой на Base
. Внутренне ссылка с понижением к ссылке на Derived
типизированным способом: приведение к понижению будет успешным только в тех случаях, когда объект, на который указывает ссылка, действительно является экземпляром Derived
].
Вот ответ инженера поддержки Nokia, имя удалено для защиты частной жизни:
Привет,
Спасибо за предложение. У меня есть передал его нашим разработчикам, которые рассмотрит возможность его реализации для будущего выпуска. Вы можете отслеживать его с помощью следующая ссылка:
https://bugreports.qt.io/browse/QTVSADDINBUG-27
С уважением, Инженер по поддержке, Рамки, Nokia >
Первоначальный вопрос
У нас есть довольно много устаревших проектов vcproj, которые мы хотим добавить к нему Qt. В настоящее время у нас нет простого способа преобразования этих устаревших vcproj файлы в vcproj с поддержкой Qt.
Что я имею в виду под Qt-enabled?
На не-Qt-enabled vcproj, если щелкнуть правой кнопкой мыши на имени проекта в обозревателе решений все параметры, связанные с Qt, выделены серым цветом.
Было бы очень полезно, если Nokia добавит эту возможность в надстройку VSTD.
Стипендиаты Stackoverflow, если вы хотите, чтобы эта функция была реализована Nokia, пожалуйста, помогите проголосовать за нее по ссылке выше! =)
-121--1490416-Интересно, как эти люди попали в компанию в первую очередь:
Этим разработчикам не только не хватает навыков с концепциями программирования, но как правило, способность формулировать решение проблемы в коде.
Простые вещи, такие как запись циклов жесткие для них...
Вам, несомненно, нужно тратить больше времени и усилий на набор рабочей силы, как гласит старая поговорка: поспешность растрачивает деньги.
Теперь, когда вы находитесь в такой ситуации, как вы описываете, заканчивайте свой отчет (как другие намекнули), сделайте его кратким и подчеркивайте, сколько денег это стоит компании, подавайте и ждите лучшего (как вы сказали, у вас «нет возможности наказать человека»).
-121--811911- dynamic _ cast
выполняет проверку типа с использованием RTTI . Если он не будет выполнен, он вызовет исключение (если вы дали ему ссылку) или NULL, если вы дали ему указатель.
В языке C нет классов, поэтому написать dynamic_cast на этом языке невозможно. Структуры языка C не имеют методов (как следствие, у них нет виртуальных методов), поэтому в них нет ничего "динамического".
Нет, непросто. Компилятор присваивает уникальный идентификатор каждому классу, на эту информацию ссылается каждый экземпляр объекта, и именно это проверяется во время выполнения, чтобы определить, допустимо ли динамическое приведение. Вы можете создать стандартный базовый класс с этой информацией и операторами для выполнения проверки во время выполнения для этого базового класса, тогда любой производный класс будет информировать базовый класс о своем месте в иерархии классов, и любые экземпляры этих классов будут транслироваться во время выполнения через ваши операции.
править
Вот реализация, демонстрирующая один метод. Я не утверждаю, что компилятор использует что-то подобное, но я думаю, что он демонстрирует концепции:
class SafeCastableBase
{
public:
typedef long TypeID;
static TypeID s_nextTypeID;
static TypeID GetNextTypeID()
{
return s_nextTypeID++;
}
static TypeID GetTypeID()
{
return 0;
}
virtual bool CanCastTo(TypeID id)
{
if (GetTypeID() != id) { return false; }
return true;
}
template <class Target>
static Target *SafeCast(SafeCastableBase *pSource)
{
if (pSource->CanCastTo(Target::GetTypeID()))
{
return (Target*)pSource;
}
return NULL;
}
};
SafeCastableBase::TypeID SafeCastableBase::s_nextTypeID = 1;
class TypeIDInitializer
{
public:
TypeIDInitializer(SafeCastableBase::TypeID *pTypeID)
{
*pTypeID = SafeCastableBase::GetNextTypeID();
}
};
class ChildCastable : public SafeCastableBase
{
public:
static TypeID s_typeID;
static TypeID GetTypeID()
{
return s_typeID;
}
virtual bool CanCastTo(TypeID id)
{
if (GetTypeID() != id) { return SafeCastableBase::CanCastTo(id); }
return true;
}
};
SafeCastableBase::TypeID ChildCastable::s_typeID;
TypeIDInitializer ChildCastableInitializer(&ChildCastable::s_typeID);
class PeerChildCastable : public SafeCastableBase
{
public:
static TypeID s_typeID;
static TypeID GetTypeID()
{
return s_typeID;
}
virtual bool CanCastTo(TypeID id)
{
if (GetTypeID() != id) { return SafeCastableBase::CanCastTo(id); }
return true;
}
};
SafeCastableBase::TypeID PeerChildCastable::s_typeID;
TypeIDInitializer PeerChildCastableInitializer(&PeerChildCastable::s_typeID);
int _tmain(int argc, _TCHAR* argv[])
{
ChildCastable *pChild = new ChildCastable();
SafeCastableBase *pBase = new SafeCastableBase();
PeerChildCastable *pPeerChild = new PeerChildCastable();
ChildCastable *pSameChild = SafeCastableBase::SafeCast<ChildCastable>(pChild);
SafeCastableBase *pBaseToChild = SafeCastableBase::SafeCast<SafeCastableBase>(pChild);
ChildCastable *pNullDownCast = SafeCastableBase::SafeCast<ChildCastable>(pBase);
SafeCastableBase *pBaseToPeerChild = SafeCastableBase::SafeCast<SafeCastableBase>(pPeerChild);
ChildCastable *pNullCrossCast = SafeCastableBase::SafeCast<ChildCastable>(pPeerChild);
return 0;
}
Если только вы не реализуете свой собственный RTTI с ручной обкаткой (в обход системного), невозможно реализовать dynamic_cast
непосредственно в коде пользовательского уровня C++. dynamic_cast
очень сильно привязан к системе RTTI реализации C++.
Но чтобы лучше понять RTTI (и, соответственно, dynamic_cast
), вам следует ознакомиться с заголовком
и оператором typeid
. Он возвращает информацию о типе, соответствующую объекту, который у вас под рукой, и вы можете запрашивать различные (ограниченные) вещи у этих объектов информации о типе.