"LNK2019 ссылка на неразрешенный внешний символ" при вызове констуктора класса из статичной библиотеки.
При компиляции получаю ошибку:
#pragma once
#include "Object.h"
#include "String.h"
namespace MyNamespace{
namespace System
{
template <typename T>
class NArray : public NObject
{
public:
NArray(int);
NString ToString();
};
}}
#include "Array.h"
namespace MyNamespace{
namespace System
{
template<typename T>
NArray<T>::NArray(int lenght)
{
}
template<typename T>
NString NArray<T>::ToString()
{
return NString(*this);
}
}}
И если я хочу написать тип Array, который может содержать 30 различных типов, я должен создать Array<Type1>, Array<Type2>, ... Array<Type30>?
А как же тогда реализован... тот же std::vector<T>?
Если это так... я явно заблудился и зашёл не туда. Прощай, странный язык, я возвращаюсь в C#...
И вызываю соответственно:
using namespace MyNamespace::System;
int main(int count, char** args)
{
int size = 10;
NArray<int> arr(size); // тут всё и падает
}
А вот в .hpp реализацию я вынести не могу, потому что у меня циклические зависимсоти между несколькими h-файлами.
ПыСы. циклические зависимости рашаются следующим кодом:
#define MY_H_FILE
//...блаблабла
#endif
#pragma once
namespace MyNamespace{
namespace System
{
class NString;
class NObject
{
public:
virtual NString ToString() = 0;
};
}}
---
Уверен, что в NObject? От него наследуются и другие классы и они создаются нормально. Проблема только в NArray<T>
PS: Впрочем как и ToString у все того же NArray.
Ответ верен, лишь наполовину, ибо main, в данном случае, так же не инстанциирует ни конструктор, ни ToString.
-------------
В таком случае, не осознаю глубинного смысла слова "инстанциирует". Для меня это - создание экземпляра объекта. И NArray<int> arr(size); как раз оно и есть. Что же понимается под "инстанциирует конструктор" мне даже страшно представить.
...или имелось ввиду "вызов функции у экземпляра объекта"? Тогда я очень плохо представляю - как должен быть вызван конструктор уже созданного экземпляра...
В общем, проблема всё ещё актуальна. =\
Тупик? Решения нет? #ifndef и #pragma once не помогают...
Как только появляются взаимные инклюды - компилятор умирает.
Тупик? Решения нет? #ifndef и #pragma once не помогают...
Как только появляются взаимные инклюды - компилятор умирает.
Буквы в студию.
Ошибка 2 error C2027: использование неопределенного типа "MyNamespace::System::NString"
Ошибка 3 error C2027: использование неопределенного типа "MyNamespace::System::NString"
Ошибка 4 error C2143: синтаксическая ошибка: отсутствие ";" перед "<"
Ошибка 5 error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
Ошибка 6 error C2238: непредвиденные лексемы перед ";"
#pragma once
namespace MyNamespace{
namespace System
{
class NString;
class NObject
{
public:
virtual NString ToString() = 0;
};
}}
#pragma once
#include "Object.h"
#include "Int32.h"
#include "String.h"
namespace MyNamespace{
namespace System
{
template <typename T>
class NArray : public NObject
{
public:
NArray()
{
}
NArray(int lenght)
{
}
NString ToString()
{
return NString(*this);
}
};
}}
#pragma once
#include "Object.h"
#include "Array.hpp"
namespace MyNamespace{
namespace System
{
class NString : public NObject
{
public:
NString(void);
NString(NObject&);
NString ToString();
private:
NArray<int> _buff;
int lenght;
};
}}
Так нельзя:
class B
{
A foo();
}
class B
{
A* foo();
}
Ссылку я вернуть не могу, так как объект временный.
Указатель я возвращать не буду, так как освобождать человек должен только то, что он создал самостоятельно.
По части class A; class B; Можно тоже самое с шаблонами?
Сей спидхак я опробовал - либо неопределен T (как у тебя), либо, если добавить {} - двойное объявление шаблона.
Вот такие пироги.
(Ну и если уж возвращать указатель, то std::shared_ptr, а не * :))
Компилятор тебе не даст вернуть неполный тип. Ему нужно знать размер объекта чтоб его вернуть а размер NObject неузнаешь пока не получишь размер NString, размер которого не узнаешь пока не получишь размер NObject ....а вот размер указателя он прекрасно знает.
P..S. Всю свою программерскую жизнь я только и слышал о том, какой гибкий С++ и как ограничены все прочие языки в сравнении с ним. И вот результат. В кои то веки нашёл время заняться освоением С++ и за один день набрал столько минусов, что хочется забыть о нём, как о страшном сне и вернуться к родным C# и ассёмблеру.
P..S. Всю свою программерскую жизнь я только и слышал о том, какой гибкий С++ и как ограничены все прочие языки в сравнении с ним.
Да ну, имхо любой скриптовый язык намного более гибкий чем c++. Другое дело что C++ самый гибкий из всех языков, которые транслируются в нативный код платформы и не требуют таскать с собой сотню метров фреймворка
Да лааадно... какие? Шаблоны из библиотеки? Потому что это библиотеки, а не шарповские "сборки". Нельзя вернуть неполный тип? В шарпе вообще всё обращение к объектам идет по хендлам в кучу, за которой следит сборщик мусора. Ну а вообще проблема заключается в том, что ты хочешь писать на C++ как на C# - это разные вещи, просто прими это.
Основные претензии в общем-то не столько к самому С++, сколько к компиляторам и линкерам. Инлюкды ему пропиши. Либы ему пропиши. Подкаталоги он не видит. В коде #pragma once / #ifndef втыкай (а то бестолковый компилятор не знает, что один файл нужно скомпилировать один раз, а не 100500). Можно сделать кучу ошибок (по неопытности, невнимательности), а он скомпилит и не почешется. Зато укажешь где-нибудь неверное имя типа, а он тебе десяток ошибок - не то, что ни на эту строчку, а вообще в другом файле укажет. Интелесенс нормальный только в 2012ой студии появился. В общем... кошмар.
(Возможно, в каких-нибудь Eclipse + clang или Qt + gcc всё иначе, но увы - билдить приходится в студии)