virtual
требуется реализация. Объявление деструктора по-прежнему требует определения его (в отличие от обычной функции):
struct X
{
virtual ~X() = 0;
};
struct Y : X
{
~Y() {}
};
int main()
{
Y y;
}
//X::~X(){} //uncomment this line for successful definition
Это происходит потому, что деструкторы базового класса вызывается, когда объект уничтожается неявно, поэтому требуется определение.
virtual
методы должны быть реализованы или определены как чистые. Это похоже на методы не virtual
без определения, с добавлением аргументов, которые генерирует чистая декларация dummy vtable, и вы можете получить ошибку компоновщика без использования функции:
struct X
{
virtual void foo();
};
struct Y : X
{
void foo() {}
};
int main()
{
Y y; //linker error although there was no call to X::foo
}
Чтобы это сработало, объявите X::foo()
чистым:
struct X
{
virtual void foo() = 0;
};
virtual
Некоторые члены должны быть определены, даже если они явно не используются:
struct A
{
~A();
};
Следующие ошибки приведут к ошибке:
A a; //destructor undefined
Реализация может быть встроенной в самом определении класса:
struct A
{
~A() {}
};
или снаружи:
A::~A() {}
Если реализация вне определения класса, но в заголовке, методы должны быть отмечены как inline
, чтобы предотвратить множественное определение.
Все используемые методы-члены должны быть определены, если они используются.
struct A
{
void foo();
};
void foo() {}
int main()
{
A a;
a.foo();
}
Определение должно быть
void A::foo() {}
static
. Члены данных должны быть определены вне класса в единственная единица перевода: struct X
{
static int x;
};
int main()
{
int x = X::x;
}
//int X::x; //uncomment this line to define X::x
Инициализатор может быть предоставлен для элемента данных static
const
типа интеграла или перечисления в определении класса; однако odr-использование этого элемента по-прежнему потребует определения области пространства имен, как описано выше. C ++ 11 позволяет инициализировать внутри класса для всех членов static const
данных.
У меня точно такая же проблема, как и выше, и взял меня целый день, чтобы понять, что мне не нравится мой подход к новой линии. Вместо этого я использовал один и тот же код с подходом с двоеточием. Например, мой исходный код с использованием новой строки (которая забросила ту же ошибку, что и ваша):
Y=1
while test "$Y" -le "20"
do
echo "Number $Y"
Y=$[Y+1]
done
И используя код с точкой с запятой с работающим чудом:
Y=1 ; while test "$Y" -le "20"; do echo "Number $Y"; Y=$[Y+1] ; done
Я замечаю эта же проблема возникает и для других команд, используя подход новой строки, поэтому я думаю, что буду придерживаться точки с запятой для моего будущего кода.
Вы можете решить эту проблему, не имея смешанных проблем с новой строкой (по крайней мере, в моей оболочке, которая является GNU bash v4.3.30):
#!/bin/bash
# foo.sh
function foo() {
echo "I am quoting a thing `$1' inside a function."
}
while [ "$input" != "y" ]; do
read -p "Hit `y' to continue: " -n 1 input
echo
done
foo "What could possibly go wrong?"
$ ./foo.sh
./foo.sh: line 11: syntax error near unexpected token `done'
./foo.sh: line 11: `done'
Это потому, что bash расширяет обратные линии внутри строк с двойными кавычками (см. руководство bash в , цитируя и подстановку команд ), и перед поиском соответствующего обратного хода интерпретирует любые дополнительные двойные кавычки как часть Подстановка команды:
$ echo "Command substitution happens inside double-quoted strings: `ls`"
Command substitution happens inside double-quoted strings: foo.sh
$ echo "..even with double quotes: `grep -E "^foo|wrong" foo.sh`"
..even with double quotes: foo "What could possibly go wrong?"
Вы можете обойти это, избегая обратных шагов в своей строке с помощью обратного слэша или используя строку с одним кавычком.
Я не очень конечно, почему это только дает одно сообщение об ошибке, но я думаю, что это связано с определением функции:
#!/bin/bash
# a.sh
function a() {
echo "Thing's `quoted'"
}
a
while true; do
echo "Other `quote'"
done
#!/bin/bash
# b.sh
echo "Thing's `quoted'"
while true; do
echo "Other `quote'"
done
$ ./a.sh
./a.sh: line 10: syntax error near unexpected token `done'
./a.sh: line 10: `done'
$ ./b.sh
./b.sh: command substitution: line 6: unexpected EOF while looking for matching `''
./b.sh: command substitution: line 9: syntax error: unexpected end of file
Thing's quote'
./b.sh: line 7: syntax error near unexpected token `done'
./b.sh: line 7: `done'
Какая ошибка вы получаете?
$ bash file.sh
test.sh: line 8: syntax error: unexpected end of file
Если вы получите эту ошибку, у вас могут быть неудачные окончания строк. Unix использует <LF>
в конце файла, а Windows использует <CR><LF>
. Этот символ <CR>
интерпретируется как символ.
Вы можете использовать od -a test.sh
, чтобы увидеть невидимые символы в файле.
$ od -a test.sh
0000000 # ! / b i n / b a s h cr nl # sp cr
0000020 nl w h i l e sp : cr nl d o cr nl sp sp
0000040 sp sp e c h o sp " P r e s s sp [ C
0000060 T R L + C ] sp t o sp s t o p " cr
0000100 nl sp sp sp sp s l e e p sp 1 cr nl d o
0000120 n e cr nl
0000124
sp
обозначает пробел, ht
обозначает вкладку, cr
обозначает <CR>
, а nl
обозначает <LF>
. Обратите внимание, что все строки заканчиваются на cr
, за которым следует символ nl
.
Вы также можете использовать cat -v test.sh
, если ваша команда cat
принимает параметр -v
.
Если у вас есть dos2unix
на вашем поле, вы можете использовать эту команду для исправить файл:
$ dos2unix test.sh
Открыть новый файл с именем foobar
nano -w foobar
Входной скрипт
#!/bin/bash
while [ 0 = 0 ]; do
echo "Press [CTRL+C] to stop.."
sleep 1
done;
Выход и сохранение
CTRL + X, затем Y и Enter
Установить исполняемый скрипт и запустить
chmod +x foobar
./foobar
Я получал ту же ошибку на Cygwin; Я сделал следующее (один из них исправил его):
TABS
в SPACES
dos2unix
в файле .(ba)sh
Иногда эта ошибка возникает из-за непредвиденных символов CR в файле, обычно потому, что файл был сгенерирован в системе Windows, которая использует окончания строки CR. Вы можете исправить это, выполнив os2unix
или tr
, например:
tr -d '\ 015' & lt; yourscript.sh> newscript.sh
blockquote>Это удаляет из файла любые символы CR.
Отредактируйте свой код в любой среде Linux, тогда вы не столкнетесь с этой проблемой. Если редактировать в блокнот Windows любое пространство, возьмите его как ^ M.
Может помочь кому-то еще: я столкнулся с такими же проблемами, когда я сделал некоторую «копию-вставку» из документа Microsoft Word, где я сделал заметки, для моего сценария оболочки.
Повторная запись вручную, тот же самый код в скрипте просто решил это.
Сначала было непонятно, я думаю, что скрытые символы и / или форматирование Word были проблемой. Очевидный, но не видимый ... Я потерял около часа на этом (я не эксперт в оболочке, как вы могли догадаться ...)
Выполнить cat -v file.sh
.
У вас, скорее всего, есть возврат каретки или свободное пространство в вашем файле. cat -v
отобразит их как ^M
и M-BM-
или M-
соответственно. Он также будет показывать любые другие странные символы, которые вы, возможно, попали в ваш файл.
Удалите разрывы строк Windows с помощью
tr -d '\r' file.sh > fixedfile.sh