Pregunta

¿Alguien sabe cómo puedo, en independiente de la plataforma de código C++ evitar que un objeto se creó en el montón?Es decir, para una clase de "Foo", quiero prevenir a los usuarios de hacer esto:

Foo *ptr = new Foo;

y sólo les permiten hacer esto:

Foo myfooObject;

¿Alguien tiene alguna idea?

Saludos,

¿Fue útil?

Solución

Nick respuesta es un buen punto de partida, pero incompleta, ya que en realidad necesitan de sobrecarga:

private:
    void* operator new(size_t);          // standard new
    void* operator new(size_t, void*);   // placement new
    void* operator new[](size_t);        // array new
    void* operator new[](size_t, void*); // placement array new

(Buenas prácticas de codificación sugeriría usted también debe sobrecargar el delete y delete[] operadores -- me gustaría, pero ya no van a conseguir llamado no es realmente de ser necesario).

Pauldoo también es correcto que esto no sobrevivir a la agregación en Foo, a pesar de que hace sobrevivir a la herencia de Foo.Usted podría hacer algunas plantilla de meta-programación de la magia para AYUDAR a prevenir esto, pero no sería inmune al "mal usuarios" y por lo tanto es probable que no vale la pena la complicación.Documentación de cómo debe ser utilizado, y de la revisión de código para asegurarse de que se utiliza de manera adecuada, son los únicos ~100% camino.

Otros consejos

Usted podría sobrecargar nuevo de Foo y hacerlo privado.Esto significa que el compilador podría gemir...a menos que usted está creando una instancia de Foo en el montón de dentro de los Foo.Para coger este caso, usted podría simplemente no escribir Foo nuevo método y, a continuación, el vinculador iba a quejar undefined symbols.

class Foo {
private:
  void* operator new(size_t size);
};

PS.Sí, sé que esto puede evitarse fácilmente.Realmente no estoy recomendando - creo que es una mala idea - sólo estaba respondiendo a la pregunta!;-)

No sé cómo hacerlo de forma fiable y en una manera portátil..pero..

Si el objeto está en la pila, entonces usted podría ser capaz de hacer valer dentro del constructor de que el valor de 'este' siempre está cerca del puntero de pila.Hay una buena probabilidad de que el objeto será en la pila si este es el caso.

Yo creo que no todas las plataformas de aplicar sus pilas en la misma dirección, así que usted puede ser que desee hacer una prueba cuando se inicia la aplicación para verificar la manera en la que la pila crece..O hacer algo de dulce de leche:

FooClass::FooClass() {
    char dummy;
    ptrdiff_t displacement = &dummy - reinterpret_cast<char*>(this);
    if (displacement > 10000 || displacement < -10000) {
        throw "Not on the stack - maybe..";
    }
}

@Nick

Esto podría evitarse mediante la creación de una clase que deriva de o agregados de Foo.Creo que lo que me sugieren (aunque no es robusta) seguiría trabajando para la derivada y de la agregación de las clases.

E. g:

struct MyStruct {
    Foo m_foo;
};

MyStruct* p = new MyStruct();

Aquí he creado una instancia de 'Foo' en el montón, sin pasar por Foo ocultas del nuevo operador.

Debido a que la depuración de los encabezados pueden reemplazar el operador de la nueva firma, es mejor utilizar el ...firmas como un remedio:

private:
void* operator new(size_t, ...) = delete;
void* operator new[](size_t, ...) = delete;

Puede declarar una función llamada "operador nuevo" dentro de la clase Foo que podría bloquear el acceso a la forma normal de nuevo.

Es este el tipo de comportamiento que usted desea ?

Usted podría declarar como una interfaz y control de la implementación de la clase más directamente desde su propio código.

esto se puede evitar haciendo que los constructores privados y proporcionando un miembro estático para crear un objeto en la pila

Class Foo
{
    private:
        Foo();
        Foo(Foo& );
    public:
        static Foo GenerateInstance() { 
            Foo a ; return a; 
        }
}

esto hará que la creación del objeto siempre en la pila.

No seguro si esto se ofrece en tiempo de compilación oportunidades, pero has mirado en la sobrecarga de la 'nueva' operador para su clase?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top