Вы можете попробовать fit-content
(CSS3):
div {
width: fit-content;
/* To adjust the height as well */
height: fit-content;
}
На практике вы должны использовать только виртуальное наследование для определения интерфейсов, поскольку они обычно используются с множественным наследованием, чтобы гарантировать, что только одна версия класса присутствует в производном классе. А чистые интерфейсы - самая безопасная форма множественного наследования. Конечно, если вы знаете, что делаете, вы можете использовать множественное наследование по своему усмотрению, но это может привести к неустойчивому коду, если вы не будете осторожны.
Самый большой недостаток виртуального наследования - это то, что их конструкторы принимают параметры. Если вам нужно передать параметры конструктору виртуального базового класса, вы заставляете все производные классы явно вызывать конструктор (они не могут полагаться на базовый класс, вызывающий конструктор). Я сделал домашнюю работу после комментария Мартина, спасибо Марин. Первая строка не совсем верна:
На практике вы должны использовать только виртуальное наследование для определения интерфейсы, как они обычно используются с множественным наследованием для обеспечения что только одна версия класса присутствует в производном классе.
Виртуальное наследование не имеет значения, если базовый класс является чистым интерфейсом (за исключением немного других ошибок компилятора в vc8, если не все методы реализованы). Это имеет значение только в том случае, если в базовом классе есть данные, в этом случае вы получите ромб, а не U-образную форму
Non virtual virtual
A A A
| | / \
B C B C
\ / \ /
D D
В виртуальном случае B и C используют одну и ту же копию A.
Однако я все еще согласен со всем остальным, что чистые интерфейсы являются самой безопасной формой множественного наследования, даже если они не требуют виртуального наследования. И тот факт, что параметры конструктора и виртуальное наследование - это боль.
Основной совет - иметь конструктор по умолчанию в виртуальной базе. Если вы этого не сделаете, то каждый наиболее производный класс (т.е. любой подкласс) должен явно вызывать виртуальный базовый ctor, и это приводит к тому, что разгневанные коллеги стучатся в дверь вашего офиса ...
class VirtualBase {
public:
explicit VirtualBase( int i ) : m_i( i ) {}
virtual ~VirtualBase() {}
private:
int m_i;
};
class Derived : public virtual VirtualBase {
public:
Derived() : VirtualBase( 0 ) {} // ok, this is to be expected
};
class DerivedDerived : public Derived { // no VirtualBase visible
public:
DerivedDerived() : Derived() {} // ok? no: error: need to explicitly
// call VirtualBase::VirtualBase!!
DerivedDerived() : VirtualBase( 0 ), Derived() {} // ok
};
a) члены должны быть закрытыми - поэтому у вас могут возникнуть проблемы с их использованием в производных классах (поэтому вам нужно добавить методы получения и установки, которые взорвут ваш интерфейс)
b) не объявляйте то, что вы в настоящее время не объявляете use - объявлять переменные только в классах, которые имеют к ним доступ / используют
c) виртуальные базовые классы должны содержать только интерфейсы / виртуальные методы, не более того
Я надеюсь, что это немного поможет, даже если мои причины не идеальны и завершено :)
ciao, Крис
Я никогда не видел этой рекомендации.
Класс - это набор тесно связанных функций и данных. Цель базового класса состоит в том, чтобы иметь общий набор функций и данных, доступных для повторного использования производными классами.
Я думаю, что ограничение себя, чтобы не иметь членов данных или нечистых виртуальных функций в базовых классах, уменьшит количество повторного использования кода, что в конечном итоге ведет к снижению надежности кода.
Базовые классы с полным абстрагированием, которые используются для моделирования интерфейсов в C ++, не должны иметь членов данных - потому что они описывают интерфейс , а состояние экземпляра является детали реализации.
Помимо этого, базовые классы, содержащие виртуальные функции, вполне могут иметь элементы данных. Однако применяются обычные правила: