Use override & final instead of just using virtual.

This is safer than using virtual and this lead to a minor
bug fixes.

Change-Id: Id69cb1cc569bf6bf245f22f029c7871b6c712568
diff --git a/internal/ceres/accelerate_sparse.h b/internal/ceres/accelerate_sparse.h
index 068834c..43b4ea5 100644
--- a/internal/ceres/accelerate_sparse.h
+++ b/internal/ceres/accelerate_sparse.h
@@ -117,12 +117,12 @@
 
   // SparseCholesky interface.
   virtual ~AppleAccelerateCholesky();
-  virtual CompressedRowSparseMatrix::StorageType StorageType() const;
-  virtual LinearSolverTerminationType Factorize(CompressedRowSparseMatrix* lhs,
-                                                std::string* message);
-  virtual LinearSolverTerminationType Solve(const double* rhs,
-                                            double* solution,
-                                            std::string* message);
+  CompressedRowSparseMatrix::StorageType StorageType() const;
+  LinearSolverTerminationType Factorize(CompressedRowSparseMatrix* lhs,
+                                        std::string* message) final;
+  LinearSolverTerminationType Solve(const double* rhs,
+                                    double* solution,
+                                    std::string* message) final ;
 
  private:
   AppleAccelerateCholesky(const OrderingType ordering_type);
diff --git a/internal/ceres/autodiff_cost_function_benchmark.cc b/internal/ceres/autodiff_cost_function_benchmark.cc
index b9c106e..d9a1e57 100644
--- a/internal/ceres/autodiff_cost_function_benchmark.cc
+++ b/internal/ceres/autodiff_cost_function_benchmark.cc
@@ -62,9 +62,9 @@
  public:
   Rat43Automatic(const Rat43CostFunctor* functor) : functor_(functor) {}
   virtual ~Rat43Automatic() {}
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     if (!jacobians) {
       return (*functor_)(parameters[0], residuals);
     }
diff --git a/internal/ceres/block_jacobi_preconditioner.h b/internal/ceres/block_jacobi_preconditioner.h
index a6d19e8..856b506 100644
--- a/internal/ceres/block_jacobi_preconditioner.h
+++ b/internal/ceres/block_jacobi_preconditioner.h
@@ -61,13 +61,13 @@
   virtual ~BlockJacobiPreconditioner();
 
   // Preconditioner interface
-  virtual void RightMultiply(const double* x, double* y) const;
-  virtual int num_rows() const { return m_->num_rows(); }
-  virtual int num_cols() const { return m_->num_rows(); }
+  void RightMultiply(const double* x, double* y) const final;
+  int num_rows() const final { return m_->num_rows(); }
+  int num_cols() const final { return m_->num_rows(); }
   const BlockRandomAccessDiagonalMatrix& matrix() const { return *m_; }
 
  private:
-  virtual bool UpdateImpl(const BlockSparseMatrix& A, const double* D);
+  bool UpdateImpl(const BlockSparseMatrix& A, const double* D) final;
 
   std::unique_ptr<BlockRandomAccessDiagonalMatrix> m_;
 };
diff --git a/internal/ceres/block_random_access_dense_matrix.h b/internal/ceres/block_random_access_dense_matrix.h
index e1dca84..8c5e252 100644
--- a/internal/ceres/block_random_access_dense_matrix.h
+++ b/internal/ceres/block_random_access_dense_matrix.h
@@ -64,21 +64,21 @@
   virtual ~BlockRandomAccessDenseMatrix();
 
   // BlockRandomAccessMatrix interface.
-  virtual CellInfo* GetCell(int row_block_id,
-                            int col_block_id,
-                            int* row,
-                            int* col,
-                            int* row_stride,
-                            int* col_stride);
+  CellInfo* GetCell(int row_block_id,
+                    int col_block_id,
+                    int* row,
+                    int* col,
+                    int* row_stride,
+                    int* col_stride) final;
 
   // This is not a thread safe method, it assumes that no cell is
   // locked.
-  virtual void SetZero();
+  void SetZero() final;
 
   // Since the matrix is square with the same row and column block
   // structure, num_rows() = num_cols().
-  virtual int num_rows() const { return num_rows_; }
-  virtual int num_cols() const { return num_rows_; }
+  int num_rows() const final { return num_rows_; }
+  int num_cols() const final { return num_rows_; }
 
   // The underlying matrix storing the cells.
   const double* values() const { return values_.get(); }
diff --git a/internal/ceres/block_random_access_diagonal_matrix.h b/internal/ceres/block_random_access_diagonal_matrix.h
index 6ad976f..3bda7d1 100644
--- a/internal/ceres/block_random_access_diagonal_matrix.h
+++ b/internal/ceres/block_random_access_diagonal_matrix.h
@@ -58,16 +58,16 @@
   virtual ~BlockRandomAccessDiagonalMatrix();
 
   // BlockRandomAccessMatrix Interface.
-  virtual CellInfo* GetCell(int row_block_id,
-                            int col_block_id,
-                            int* row,
-                            int* col,
-                            int* row_stride,
-                            int* col_stride);
+  CellInfo* GetCell(int row_block_id,
+                    int col_block_id,
+                    int* row,
+                    int* col,
+                    int* row_stride,
+                    int* col_stride) final;
 
   // This is not a thread safe method, it assumes that no cell is
   // locked.
-  virtual void SetZero();
+  void SetZero() final;
 
   // Invert the matrix assuming that each block is positive definite.
   void Invert();
@@ -76,8 +76,8 @@
   void RightMultiply(const double* x, double* y) const;
 
   // Since the matrix is square, num_rows() == num_cols().
-  virtual int num_rows() const { return tsm_->num_rows(); }
-  virtual int num_cols() const { return tsm_->num_cols(); }
+  int num_rows() const final { return tsm_->num_rows(); }
+  int num_cols() const final { return tsm_->num_cols(); }
 
   const TripletSparseMatrix* matrix() const { return tsm_.get(); }
   TripletSparseMatrix* mutable_matrix() { return tsm_.get(); }
diff --git a/internal/ceres/block_random_access_matrix.h b/internal/ceres/block_random_access_matrix.h
index 2187fcd..6fcf0dc 100644
--- a/internal/ceres/block_random_access_matrix.h
+++ b/internal/ceres/block_random_access_matrix.h
@@ -84,13 +84,8 @@
 // Structure to carry a pointer to the array containing a cell and the
 // mutex guarding it.
 struct CellInfo {
-  CellInfo()
-      : values(NULL) {
-  }
-
-  explicit CellInfo(double* ptr)
-      : values(ptr) {
-  }
+  CellInfo() : values(nullptr) {}
+  explicit CellInfo(double* values) : values(values) {}
 
   double* values;
   std::mutex m;
diff --git a/internal/ceres/block_random_access_sparse_matrix.h b/internal/ceres/block_random_access_sparse_matrix.h
index 12244a5..d542a3d 100644
--- a/internal/ceres/block_random_access_sparse_matrix.h
+++ b/internal/ceres/block_random_access_sparse_matrix.h
@@ -67,16 +67,16 @@
   virtual ~BlockRandomAccessSparseMatrix();
 
   // BlockRandomAccessMatrix Interface.
-  virtual CellInfo* GetCell(int row_block_id,
-                            int col_block_id,
-                            int* row,
-                            int* col,
-                            int* row_stride,
-                            int* col_stride);
+  CellInfo* GetCell(int row_block_id,
+                    int col_block_id,
+                    int* row,
+                    int* col,
+                    int* row_stride,
+                    int* col_stride) final;
 
   // This is not a thread safe method, it assumes that no cell is
   // locked.
-  virtual void SetZero();
+  void SetZero() final;
 
   // Assume that the matrix is symmetric and only one half of the
   // matrix is stored.
@@ -85,8 +85,8 @@
   void SymmetricRightMultiply(const double* x, double* y) const;
 
   // Since the matrix is square, num_rows() == num_cols().
-  virtual int num_rows() const { return tsm_->num_rows(); }
-  virtual int num_cols() const { return tsm_->num_cols(); }
+  int num_rows() const final { return tsm_->num_rows(); }
+  int num_cols() const final { return tsm_->num_cols(); }
 
   // Access to the underlying matrix object.
   const TripletSparseMatrix* matrix() const { return tsm_.get(); }
diff --git a/internal/ceres/block_random_access_sparse_matrix_test.cc b/internal/ceres/block_random_access_sparse_matrix_test.cc
index 9ca9c46..fa0698f 100644
--- a/internal/ceres/block_random_access_sparse_matrix_test.cc
+++ b/internal/ceres/block_random_access_sparse_matrix_test.cc
@@ -139,7 +139,7 @@
 // test it.
 class BlockRandomAccessSparseMatrixTest : public ::testing::Test {
  public:
-  virtual void SetUp() {
+  void SetUp() final {
     vector<int> blocks;
     blocks.push_back(1);
     set<pair<int, int>> block_pairs;
diff --git a/internal/ceres/block_sparse_matrix.h b/internal/ceres/block_sparse_matrix.h
index 366ef87..4bdbee8 100644
--- a/internal/ceres/block_sparse_matrix.h
+++ b/internal/ceres/block_sparse_matrix.h
@@ -69,19 +69,19 @@
   virtual ~BlockSparseMatrix();
 
   // Implementation of SparseMatrix interface.
-  virtual void SetZero();
-  virtual void RightMultiply(const double* x, double* y) const;
-  virtual void LeftMultiply(const double* x, double* y) const;
-  virtual void SquaredColumnNorm(double* x) const;
-  virtual void ScaleColumns(const double* scale);
-  virtual void ToDenseMatrix(Matrix* dense_matrix) const;
-  virtual void ToTextFile(FILE* file) const;
+  void SetZero() final;
+  void RightMultiply(const double* x, double* y) const final;
+  void LeftMultiply(const double* x, double* y) const final;
+  void SquaredColumnNorm(double* x) const final;
+  void ScaleColumns(const double* scale) final;
+  void ToDenseMatrix(Matrix* dense_matrix) const final;
+  void ToTextFile(FILE* file) const final;
 
-  virtual int num_rows()         const { return num_rows_;     }
-  virtual int num_cols()         const { return num_cols_;     }
-  virtual int num_nonzeros()     const { return num_nonzeros_; }
-  virtual const double* values() const { return values_.get(); }
-  virtual double* mutable_values()     { return values_.get(); }
+  int num_rows()         const final { return num_rows_;     }
+  int num_cols()         const final { return num_cols_;     }
+  int num_nonzeros()     const final { return num_nonzeros_; }
+  const double* values() const final { return values_.get(); }
+  double* mutable_values()     final { return values_.get(); }
 
   void ToTripletSparseMatrix(TripletSparseMatrix* matrix) const;
   const CompressedRowBlockStructure* block_structure() const;
diff --git a/internal/ceres/block_sparse_matrix_test.cc b/internal/ceres/block_sparse_matrix_test.cc
index 26fa9a2..0c88bd9 100644
--- a/internal/ceres/block_sparse_matrix_test.cc
+++ b/internal/ceres/block_sparse_matrix_test.cc
@@ -44,7 +44,7 @@
 
 class BlockSparseMatrixTest : public ::testing::Test {
  protected :
-  virtual void SetUp() {
+  void SetUp() final {
     std::unique_ptr<LinearLeastSquaresProblem> problem(
         CreateLinearLeastSquaresProblemFromId(2));
     CHECK(problem != nullptr);
diff --git a/internal/ceres/c_api.cc b/internal/ceres/c_api.cc
index ada8f3e..2244909 100644
--- a/internal/ceres/c_api.cc
+++ b/internal/ceres/c_api.cc
@@ -80,9 +80,9 @@
 
   virtual ~CallbackCostFunction() {}
 
-  virtual bool Evaluate(double const* const* parameters,
+  bool Evaluate(double const* const* parameters,
                         double* residuals,
-                        double** jacobians) const {
+                        double** jacobians) const final {
     return (*cost_function_)(user_data_,
                              const_cast<double**>(parameters),
                              residuals,
@@ -101,7 +101,7 @@
   explicit CallbackLossFunction(ceres_loss_function_t loss_function,
                                 void* user_data)
     : loss_function_(loss_function), user_data_(user_data) {}
-  virtual void Evaluate(double sq_norm, double* rho) const {
+  void Evaluate(double sq_norm, double* rho) const final {
     (*loss_function_)(user_data_, sq_norm, rho);
   }
 
diff --git a/internal/ceres/callbacks.h b/internal/ceres/callbacks.h
index 288d6ae..d68bf7f 100644
--- a/internal/ceres/callbacks.h
+++ b/internal/ceres/callbacks.h
@@ -46,7 +46,7 @@
  public:
   StateUpdatingCallback(Program* program, double* parameters);
   virtual ~StateUpdatingCallback();
-  virtual CallbackReturnType operator()(const IterationSummary& summary);
+  CallbackReturnType operator()(const IterationSummary& summary) final;
  private:
   Program* program_;
   double* parameters_;
@@ -60,7 +60,7 @@
                                              const double* internal_parameters,
                                              double* user_parameters);
   virtual ~GradientProblemSolverStateUpdatingCallback();
-  virtual CallbackReturnType operator()(const IterationSummary& summary);
+  CallbackReturnType operator()(const IterationSummary& summary) final;
  private:
   int num_parameters_;
   const double* internal_parameters_;
@@ -73,7 +73,7 @@
  public:
   LoggingCallback(MinimizerType minimizer_type, bool log_to_stdout);
   virtual ~LoggingCallback();
-  virtual CallbackReturnType operator()(const IterationSummary& summary);
+  CallbackReturnType operator()(const IterationSummary& summary) final;
 
  private:
   const MinimizerType minimizer_type;
diff --git a/internal/ceres/canonical_views_clustering_test.cc b/internal/ceres/canonical_views_clustering_test.cc
index a8db293..42e05bc 100644
--- a/internal/ceres/canonical_views_clustering_test.cc
+++ b/internal/ceres/canonical_views_clustering_test.cc
@@ -41,7 +41,7 @@
 const int kVertexIds[] = {0, 1, 2, 3};
 class CanonicalViewsTest : public ::testing::Test {
  protected:
-  virtual void SetUp() {
+  void SetUp() final {
     // The graph structure is as follows.
     //
     // Vertex weights:   0      2      2      0
diff --git a/internal/ceres/cgnr_linear_operator.h b/internal/ceres/cgnr_linear_operator.h
index ad0c627..8e8febc 100644
--- a/internal/ceres/cgnr_linear_operator.h
+++ b/internal/ceres/cgnr_linear_operator.h
@@ -84,7 +84,7 @@
   }
   virtual ~CgnrLinearOperator() {}
 
-  virtual void RightMultiply(const double* x, double* y) const {
+  void RightMultiply(const double* x, double* y) const final {
     std::fill(z_.get(), z_.get() + A_.num_rows(), 0.0);
 
     // z = Ax
@@ -101,12 +101,12 @@
     }
   }
 
-  virtual void LeftMultiply(const double* x, double* y) const {
+  void LeftMultiply(const double* x, double* y) const final {
     RightMultiply(x, y);
   }
 
-  virtual int num_rows() const { return A_.num_cols(); }
-  virtual int num_cols() const { return A_.num_cols(); }
+  int num_rows() const final { return A_.num_cols(); }
+  int num_cols() const final { return A_.num_cols(); }
 
  private:
   const LinearOperator& A_;
diff --git a/internal/ceres/cgnr_solver.h b/internal/ceres/cgnr_solver.h
index 0bd1883..5292733 100644
--- a/internal/ceres/cgnr_solver.h
+++ b/internal/ceres/cgnr_solver.h
@@ -55,11 +55,11 @@
   void operator=(const CgnrSolver&) = delete;
   virtual ~CgnrSolver();
 
-  virtual Summary SolveImpl(
+  Summary SolveImpl(
       BlockSparseMatrix* A,
       const double* b,
       const LinearSolver::PerSolveOptions& per_solve_options,
-      double* x);
+      double* x) final;
 
  private:
   const LinearSolver::Options options_;
diff --git a/internal/ceres/compressed_row_sparse_matrix.h b/internal/ceres/compressed_row_sparse_matrix.h
index 2b51b9b..758b40b 100644
--- a/internal/ceres/compressed_row_sparse_matrix.h
+++ b/internal/ceres/compressed_row_sparse_matrix.h
@@ -100,18 +100,18 @@
 
   // SparseMatrix interface.
   virtual ~CompressedRowSparseMatrix();
-  virtual void SetZero();
-  virtual void RightMultiply(const double* x, double* y) const;
-  virtual void LeftMultiply(const double* x, double* y) const;
-  virtual void SquaredColumnNorm(double* x) const;
-  virtual void ScaleColumns(const double* scale);
-  virtual void ToDenseMatrix(Matrix* dense_matrix) const;
-  virtual void ToTextFile(FILE* file) const;
-  virtual int num_rows() const { return num_rows_; }
-  virtual int num_cols() const { return num_cols_; }
-  virtual int num_nonzeros() const { return rows_[num_rows_]; }
-  virtual const double* values() const { return &values_[0]; }
-  virtual double* mutable_values() { return &values_[0]; }
+  void SetZero() final;
+  void RightMultiply(const double* x, double* y) const final;
+  void LeftMultiply(const double* x, double* y) const final;
+  void SquaredColumnNorm(double* x) const final;
+  void ScaleColumns(const double* scale) final;
+  void ToDenseMatrix(Matrix* dense_matrix) const final;
+  void ToTextFile(FILE* file) const final;
+  int num_rows() const final { return num_rows_; }
+  int num_cols() const final { return num_cols_; }
+  int num_nonzeros() const final { return rows_[num_rows_]; }
+  const double* values() const final { return &values_[0]; }
+  double* mutable_values() final { return &values_[0]; }
 
   // Delete the bottom delta_rows.
   // num_rows -= delta_rows
diff --git a/internal/ceres/compressed_row_sparse_matrix_test.cc b/internal/ceres/compressed_row_sparse_matrix_test.cc
index d6cda93..214f374 100644
--- a/internal/ceres/compressed_row_sparse_matrix_test.cc
+++ b/internal/ceres/compressed_row_sparse_matrix_test.cc
@@ -71,7 +71,7 @@
 
 class CompressedRowSparseMatrixTest : public ::testing::Test {
  protected:
-  virtual void SetUp() {
+  void SetUp() final {
     std::unique_ptr<LinearLeastSquaresProblem> problem(
         CreateLinearLeastSquaresProblemFromId(1));
 
diff --git a/internal/ceres/conditioned_cost_function_test.cc b/internal/ceres/conditioned_cost_function_test.cc
index 6297451..b0705f3 100644
--- a/internal/ceres/conditioned_cost_function_test.cc
+++ b/internal/ceres/conditioned_cost_function_test.cc
@@ -51,9 +51,9 @@
     mutable_parameter_block_sizes()->push_back(1);
   }
 
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     *residuals = **parameters * a_ + b_;
     if (jacobians && *jacobians) {
       **jacobians = a_;
diff --git a/internal/ceres/conjugate_gradients_solver.h b/internal/ceres/conjugate_gradients_solver.h
index 434cde0..d89383e 100644
--- a/internal/ceres/conjugate_gradients_solver.h
+++ b/internal/ceres/conjugate_gradients_solver.h
@@ -57,10 +57,10 @@
 class ConjugateGradientsSolver : public LinearSolver {
  public:
   explicit ConjugateGradientsSolver(const LinearSolver::Options& options);
-  virtual Summary Solve(LinearOperator* A,
-                        const double* b,
-                        const LinearSolver::PerSolveOptions& per_solve_options,
-                        double* x);
+  Summary Solve(LinearOperator* A,
+                const double* b,
+                const LinearSolver::PerSolveOptions& per_solve_options,
+                double* x) final;
 
  private:
   const LinearSolver::Options options_;
diff --git a/internal/ceres/coordinate_descent_minimizer.h b/internal/ceres/coordinate_descent_minimizer.h
index 3bbcc2d..7d17d53 100644
--- a/internal/ceres/coordinate_descent_minimizer.h
+++ b/internal/ceres/coordinate_descent_minimizer.h
@@ -68,9 +68,9 @@
   // Minimizer interface.
   virtual ~CoordinateDescentMinimizer();
 
-  virtual void Minimize(const Minimizer::Options& options,
-                        double* parameters,
-                        Solver::Summary* summary);
+  void Minimize(const Minimizer::Options& options,
+                double* parameters,
+                Solver::Summary* summary) final;
 
   // Verify that each group in the ordering forms an independent set.
   static bool IsOrderingValid(const Program& program,
diff --git a/internal/ceres/covariance_test.cc b/internal/ceres/covariance_test.cc
index dea0723..ad5ffe6 100644
--- a/internal/ceres/covariance_test.cc
+++ b/internal/ceres/covariance_test.cc
@@ -63,9 +63,9 @@
     mutable_parameter_block_sizes()->push_back(parameter_block_size);
   }
 
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     for (int i = 0; i < num_residuals(); ++i) {
       residuals[i] = 1;
     }
@@ -102,9 +102,9 @@
     mutable_parameter_block_sizes()->push_back(parameter_block2_size);
   }
 
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     for (int i = 0; i < num_residuals(); ++i) {
       residuals[i] = 2;
     }
@@ -134,22 +134,22 @@
  public:
   virtual ~PolynomialParameterization() {}
 
-  virtual bool Plus(const double* x,
-                    const double* delta,
-                    double* x_plus_delta) const {
+  bool Plus(const double* x,
+            const double* delta,
+            double* x_plus_delta) const final {
     x_plus_delta[0] = delta[0] * x[0];
     x_plus_delta[1] = delta[0] * x[1];
     return true;
   }
 
-  virtual bool ComputeJacobian(const double* x, double* jacobian) const {
+  bool ComputeJacobian(const double* x, double* jacobian) const final {
     jacobian[0] = x[0];
     jacobian[1] = x[1];
     return true;
   }
 
-  virtual int GlobalSize() const { return 2; }
-  virtual int LocalSize() const { return 1; }
+  int GlobalSize() const final { return 2; }
+  int LocalSize() const final { return 1; }
 };
 
 TEST(CovarianceImpl, ComputeCovarianceSparsity) {
@@ -409,7 +409,7 @@
  protected:
   typedef map<const double*, pair<int, int>> BoundsMap;
 
-  virtual void SetUp() {
+  void SetUp() override {
     double* x = parameters_;
     double* y = x + 2;
     double* z = y + 3;
@@ -1102,7 +1102,7 @@
 
 class RankDeficientCovarianceTest : public CovarianceTest {
  protected:
-  virtual void SetUp() {
+  void SetUp() final {
     double* x = parameters_;
     double* y = x + 2;
     double* z = y + 3;
@@ -1196,7 +1196,7 @@
 
 class LargeScaleCovarianceTest : public ::testing::Test {
  protected:
-  virtual void SetUp() {
+  void SetUp() final {
     num_parameter_blocks_ = 2000;
     parameter_block_size_ = 5;
     parameters_.reset(
diff --git a/internal/ceres/cxsparse.h b/internal/ceres/cxsparse.h
index 28238d5..dc4740c 100644
--- a/internal/ceres/cxsparse.h
+++ b/internal/ceres/cxsparse.h
@@ -145,12 +145,12 @@
 
   // SparseCholesky interface.
   virtual ~CXSparseCholesky();
-  virtual CompressedRowSparseMatrix::StorageType StorageType() const;
-  virtual LinearSolverTerminationType Factorize(CompressedRowSparseMatrix* lhs,
-                                                std::string* message);
-  virtual LinearSolverTerminationType Solve(const double* rhs,
-                                            double* solution,
-                                            std::string* message);
+  CompressedRowSparseMatrix::StorageType StorageType() const final;
+  LinearSolverTerminationType Factorize(CompressedRowSparseMatrix* lhs,
+                                        std::string* message) final;
+  LinearSolverTerminationType Solve(const double* rhs,
+                                    double* solution,
+                                    std::string* message) final;
 
  private:
   CXSparseCholesky(const OrderingType ordering_type);
diff --git a/internal/ceres/dense_normal_cholesky_solver.h b/internal/ceres/dense_normal_cholesky_solver.h
index c10bd7b..976718e 100644
--- a/internal/ceres/dense_normal_cholesky_solver.h
+++ b/internal/ceres/dense_normal_cholesky_solver.h
@@ -78,11 +78,11 @@
   explicit DenseNormalCholeskySolver(const LinearSolver::Options& options);
 
  private:
-  virtual LinearSolver::Summary SolveImpl(
+  LinearSolver::Summary SolveImpl(
       DenseSparseMatrix* A,
       const double* b,
       const LinearSolver::PerSolveOptions& per_solve_options,
-      double* x);
+      double* x) final;
 
   LinearSolver::Summary SolveUsingLAPACK(
       DenseSparseMatrix* A,
diff --git a/internal/ceres/dense_qr_solver.h b/internal/ceres/dense_qr_solver.h
index 2ec124f..9ea959d 100644
--- a/internal/ceres/dense_qr_solver.h
+++ b/internal/ceres/dense_qr_solver.h
@@ -83,11 +83,11 @@
   explicit DenseQRSolver(const LinearSolver::Options& options);
 
  private:
-  virtual LinearSolver::Summary SolveImpl(
+  LinearSolver::Summary SolveImpl(
       DenseSparseMatrix* A,
       const double* b,
       const LinearSolver::PerSolveOptions& per_solve_options,
-      double* x);
+      double* x) final;
 
   LinearSolver::Summary SolveUsingEigen(
       DenseSparseMatrix* A,
diff --git a/internal/ceres/dense_sparse_matrix.h b/internal/ceres/dense_sparse_matrix.h
index e5a5483..6d3d504 100644
--- a/internal/ceres/dense_sparse_matrix.h
+++ b/internal/ceres/dense_sparse_matrix.h
@@ -55,18 +55,18 @@
   virtual ~DenseSparseMatrix() {}
 
   // SparseMatrix interface.
-  virtual void SetZero();
-  virtual void RightMultiply(const double* x, double* y) const;
-  virtual void LeftMultiply(const double* x, double* y) const;
-  virtual void SquaredColumnNorm(double* x) const;
-  virtual void ScaleColumns(const double* scale);
-  virtual void ToDenseMatrix(Matrix* dense_matrix) const;
-  virtual void ToTextFile(FILE* file) const;
-  virtual int num_rows() const;
-  virtual int num_cols() const;
-  virtual int num_nonzeros() const;
-  virtual const double* values() const { return m_.data(); }
-  virtual double* mutable_values() { return m_.data(); }
+  void SetZero() final;
+  void RightMultiply(const double* x, double* y) const final;
+  void LeftMultiply(const double* x, double* y) const final;
+  void SquaredColumnNorm(double* x) const final;
+  void ScaleColumns(const double* scale) final;
+  void ToDenseMatrix(Matrix* dense_matrix) const final;
+  void ToTextFile(FILE* file) const final;
+  int num_rows() const final;
+  int num_cols() const final;
+  int num_nonzeros() const final;
+  const double* values() const final { return m_.data(); }
+  double* mutable_values() final { return m_.data(); }
 
   ConstColMajorMatrixRef matrix() const;
   ColMajorMatrixRef mutable_matrix();
diff --git a/internal/ceres/dense_sparse_matrix_test.cc b/internal/ceres/dense_sparse_matrix_test.cc
index b8ac2ba..a0c1cd6 100644
--- a/internal/ceres/dense_sparse_matrix_test.cc
+++ b/internal/ceres/dense_sparse_matrix_test.cc
@@ -68,7 +68,7 @@
 
 class DenseSparseMatrixTest : public ::testing::Test {
  protected :
-  virtual void SetUp() {
+  void SetUp() final {
     std::unique_ptr<LinearLeastSquaresProblem> problem(
         CreateLinearLeastSquaresProblemFromId(1));
 
diff --git a/internal/ceres/dogleg_strategy.h b/internal/ceres/dogleg_strategy.h
index 11a3bb0..1150940 100644
--- a/internal/ceres/dogleg_strategy.h
+++ b/internal/ceres/dogleg_strategy.h
@@ -58,15 +58,14 @@
   virtual ~DoglegStrategy() {}
 
   // TrustRegionStrategy interface
-  virtual Summary ComputeStep(const PerSolveOptions& per_solve_options,
+  Summary ComputeStep(const PerSolveOptions& per_solve_options,
                               SparseMatrix* jacobian,
                               const double* residuals,
-                              double* step);
-  virtual void StepAccepted(double step_quality);
-  virtual void StepRejected(double step_quality);
-  virtual void StepIsInvalid();
-
-  virtual double Radius() const;
+                              double* step) final;
+  void StepAccepted(double step_quality) final;
+  void StepRejected(double step_quality) final;
+  void StepIsInvalid();
+  double Radius() const final;
 
   // These functions are predominantly for testing.
   Vector gradient() const { return gradient_; }
diff --git a/internal/ceres/dogleg_strategy_test.cc b/internal/ceres/dogleg_strategy_test.cc
index c435be6..af5b3e8 100644
--- a/internal/ceres/dogleg_strategy_test.cc
+++ b/internal/ceres/dogleg_strategy_test.cc
@@ -60,7 +60,7 @@
 // from the origin.
 class DoglegStrategyFixtureEllipse : public Fixture {
  protected:
-  virtual void SetUp() {
+  void SetUp() final {
     Matrix basis(6, 6);
     // The following lines exceed 80 characters for better readability.
     basis << -0.1046920933796121, -0.7449367449921986, -0.4190744502875876, -0.4480450716142566,  0.2375351607929440, -0.0363053418882862,  // NOLINT
@@ -98,7 +98,7 @@
 // The gradient at the origin points towards the global minimum.
 class DoglegStrategyFixtureValley : public Fixture {
  protected:
-  virtual void SetUp() {
+  void SetUp() final {
     Vector Ddiag(6);
     Ddiag << 1.0, 2.0, 4.0, 8.0, 16.0, 32.0;
 
diff --git a/internal/ceres/dynamic_autodiff_cost_function_test.cc b/internal/ceres/dynamic_autodiff_cost_function_test.cc
index 29f8d10..bec31c5 100644
--- a/internal/ceres/dynamic_autodiff_cost_function_test.cc
+++ b/internal/ceres/dynamic_autodiff_cost_function_test.cc
@@ -309,7 +309,7 @@
 
 class ThreeParameterCostFunctorTest : public ::testing::Test {
  protected:
-  virtual void SetUp() {
+  void SetUp() final {
     // Prepare the parameters.
     x_.resize(1);
     x_[0] = 0.0;
@@ -548,7 +548,7 @@
 
 class SixParameterCostFunctorTest : public ::testing::Test {
  protected:
-  virtual void SetUp() {
+  void SetUp() final {
     // Prepare the parameters.
     x0_ = 0.0;
     y0_ = 1.0;
diff --git a/internal/ceres/dynamic_compressed_row_sparse_matrix_test.cc b/internal/ceres/dynamic_compressed_row_sparse_matrix_test.cc
index 3592557..25b51ce 100644
--- a/internal/ceres/dynamic_compressed_row_sparse_matrix_test.cc
+++ b/internal/ceres/dynamic_compressed_row_sparse_matrix_test.cc
@@ -46,7 +46,7 @@
 
 class DynamicCompressedRowSparseMatrixTest : public ::testing::Test {
  protected:
-  virtual void SetUp() {
+  void SetUp() final {
     num_rows = 7;
     num_cols = 4;
 
diff --git a/internal/ceres/dynamic_numeric_diff_cost_function_test.cc b/internal/ceres/dynamic_numeric_diff_cost_function_test.cc
index b627eb7..d86cc95 100644
--- a/internal/ceres/dynamic_numeric_diff_cost_function_test.cc
+++ b/internal/ceres/dynamic_numeric_diff_cost_function_test.cc
@@ -310,7 +310,7 @@
 
 class ThreeParameterCostFunctorTest : public ::testing::Test {
  protected:
-  virtual void SetUp() {
+  void SetUp() final {
     // Prepare the parameters.
     x_.resize(1);
     x_[0] = 0.0;
diff --git a/internal/ceres/dynamic_sparse_normal_cholesky_solver.h b/internal/ceres/dynamic_sparse_normal_cholesky_solver.h
index 17be90c..4e31c7a 100644
--- a/internal/ceres/dynamic_sparse_normal_cholesky_solver.h
+++ b/internal/ceres/dynamic_sparse_normal_cholesky_solver.h
@@ -59,11 +59,11 @@
   virtual ~DynamicSparseNormalCholeskySolver() {}
 
  private:
-  virtual LinearSolver::Summary SolveImpl(
+  LinearSolver::Summary SolveImpl(
       CompressedRowSparseMatrix* A,
       const double* b,
       const LinearSolver::PerSolveOptions& options,
-      double* x);
+      double* x) final;
 
   LinearSolver::Summary SolveImplUsingSuiteSparse(
       CompressedRowSparseMatrix* A,
diff --git a/internal/ceres/dynamic_sparse_normal_cholesky_solver_test.cc b/internal/ceres/dynamic_sparse_normal_cholesky_solver_test.cc
index 4fe06f8..3d0d46d 100644
--- a/internal/ceres/dynamic_sparse_normal_cholesky_solver_test.cc
+++ b/internal/ceres/dynamic_sparse_normal_cholesky_solver_test.cc
@@ -49,7 +49,7 @@
 // sparsity.
 class DynamicSparseNormalCholeskySolverTest : public ::testing::Test {
  protected:
-  virtual void SetUp() {
+  void SetUp() final {
     std::unique_ptr<LinearLeastSquaresProblem> problem(
         CreateLinearLeastSquaresProblemFromId(1));
     A_.reset(CompressedRowSparseMatrix::FromTripletSparseMatrix(
diff --git a/internal/ceres/dynamic_sparsity_test.cc b/internal/ceres/dynamic_sparsity_test.cc
index 7c2e4ac..94ed173 100644
--- a/internal/ceres/dynamic_sparsity_test.cc
+++ b/internal/ceres/dynamic_sparsity_test.cc
@@ -288,9 +288,9 @@
     set_num_residuals(2);
   }
 
-  virtual bool Evaluate(const double* const* x,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(const double* const* x,
+                double* residuals,
+                double** jacobians) const final {
     // Convert the preimage position `t` into a segment index `i0` and the
     // line segment interpolation parameter `u`. `i1` is the index of the next
     // control point.
diff --git a/internal/ceres/eigensparse.cc b/internal/ceres/eigensparse.cc
index 9847bfd..76dba31 100644
--- a/internal/ceres/eigensparse.cc
+++ b/internal/ceres/eigensparse.cc
@@ -33,6 +33,7 @@
 #ifdef CERES_USE_EIGEN_SPARSE
 
 #include <sstream>
+
 #include "Eigen/SparseCholesky"
 #include "Eigen/SparseCore"
 #include "ceres/compressed_row_sparse_matrix.h"
@@ -48,11 +49,11 @@
  public:
   EigenSparseCholeskyTemplate() : analyzed_(false) {}
   virtual ~EigenSparseCholeskyTemplate() {}
-  virtual CompressedRowSparseMatrix::StorageType StorageType() const {
+  CompressedRowSparseMatrix::StorageType StorageType() const final {
     return CompressedRowSparseMatrix::LOWER_TRIANGULAR;
   }
 
-  virtual LinearSolverTerminationType Factorize(
+  LinearSolverTerminationType Factorize(
       const Eigen::SparseMatrix<typename Solver::Scalar>& lhs,
       std::string* message) {
     if (!analyzed_) {
@@ -104,8 +105,8 @@
     return LINEAR_SOLVER_SUCCESS;
   }
 
-  virtual LinearSolverTerminationType Factorize(CompressedRowSparseMatrix* lhs,
-                                                std::string* message) {
+  LinearSolverTerminationType Factorize(CompressedRowSparseMatrix* lhs,
+                                        std::string* message) final {
     CHECK_EQ(lhs->storage_type(), StorageType());
 
     typename Solver::Scalar* values_ptr = NULL;
diff --git a/internal/ceres/evaluation_callback_test.cc b/internal/ceres/evaluation_callback_test.cc
index dff0943..bfe788d 100644
--- a/internal/ceres/evaluation_callback_test.cc
+++ b/internal/ceres/evaluation_callback_test.cc
@@ -77,8 +77,8 @@
 
   // Evaluation callback interface. This checks that all the preconditions are
   // met at the point that Ceres calls into it.
-  virtual void PrepareForEvaluation(bool evaluate_jacobians,
-                                    bool new_evaluation_point) {
+  void PrepareForEvaluation(bool evaluate_jacobians,
+                            bool new_evaluation_point) final {
     // At this point, the incoming parameters are implicitly pushed by Ceres
     // into the user parameter blocks; in contrast to in Evaluate().
     uint64_t incoming_parameter_hash = Djb2Hash(user_parameter_block, 2);
@@ -111,9 +111,9 @@
 
   // Cost function interface. This checks that preconditions that were
   // set as part of the PrepareForEvaluation() call are met in this one.
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     // Cost function implementation of the "Wiggly Bowl" function:
     //
     //   1/2 * [(y - a*sin(x))^2 + x^2],
diff --git a/internal/ceres/evaluator_test.cc b/internal/ceres/evaluator_test.cc
index ef76be2..4f023d1 100644
--- a/internal/ceres/evaluator_test.cc
+++ b/internal/ceres/evaluator_test.cc
@@ -64,9 +64,9 @@
   explicit ParameterIgnoringCostFunction(bool succeeds = true)
       : succeeds_(succeeds) {}
 
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     for (int i = 0; i < Base::num_residuals(); ++i) {
       residuals[i] = i + 1;
     }
@@ -580,9 +580,9 @@
 // state changes.
 class ParameterSensitiveCostFunction : public SizedCostFunction<2, 2> {
  public:
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     double x1 = parameters[0][0];
     double x2 = parameters[0][1];
     residuals[0] = x1 * x1;
diff --git a/internal/ceres/gradient_checker_test.cc b/internal/ceres/gradient_checker_test.cc
index a9d439f..cd194a7 100644
--- a/internal/ceres/gradient_checker_test.cc
+++ b/internal/ceres/gradient_checker_test.cc
@@ -290,9 +290,9 @@
     set_num_residuals(residuals_offset_.size());
   }
 
-  virtual bool Evaluate(double const* const* parameter_ptrs,
-                        double* residuals_ptr,
-                        double** residual_J_params) const {
+  bool Evaluate(double const* const* parameter_ptrs,
+                double* residuals_ptr,
+                double** residual_J_params) const final {
     CHECK_GE(residual_J_params_.size(), 0.0);
     VectorRef residuals(residuals_ptr, residual_J_params_[0].rows());
     residuals = residuals_offset_;
@@ -347,22 +347,22 @@
  */
 class MatrixParameterization : public LocalParameterization {
  public:
-  virtual bool Plus(const double* x,
-                    const double* delta,
-                    double* x_plus_delta) const {
+  bool Plus(const double* x,
+            const double* delta,
+            double* x_plus_delta) const final {
     VectorRef(x_plus_delta, GlobalSize()) =
         ConstVectorRef(x, GlobalSize()) +
         (global_J_local * ConstVectorRef(delta, LocalSize()));
     return true;
   }
 
-  virtual bool ComputeJacobian(const double* /*x*/, double* jacobian) const {
+  bool ComputeJacobian(const double* /*x*/, double* jacobian) const final {
     MatrixRef(jacobian, GlobalSize(), LocalSize()) = global_J_local;
     return true;
   }
 
-  virtual int GlobalSize() const { return global_J_local.rows(); }
-  virtual int LocalSize() const { return global_J_local.cols(); }
+  int GlobalSize() const final { return global_J_local.rows(); }
+  int LocalSize() const final { return global_J_local.cols(); }
 
   Matrix global_J_local;
 };
diff --git a/internal/ceres/gradient_checking_cost_function.cc b/internal/ceres/gradient_checking_cost_function.cc
index 1afbec3..13d6c58 100644
--- a/internal/ceres/gradient_checking_cost_function.cc
+++ b/internal/ceres/gradient_checking_cost_function.cc
@@ -83,9 +83,9 @@
 
   virtual ~GradientCheckingCostFunction() { }
 
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     if (!jacobians) {
       // Nothing to check in this case; just forward.
       return function_->Evaluate(parameters, residuals, NULL);
diff --git a/internal/ceres/gradient_checking_cost_function.h b/internal/ceres/gradient_checking_cost_function.h
index b2cd26e..e9a34f7 100644
--- a/internal/ceres/gradient_checking_cost_function.h
+++ b/internal/ceres/gradient_checking_cost_function.h
@@ -52,7 +52,7 @@
 
   // Will return SOLVER_CONTINUE until a gradient error has been detected,
   // then return SOLVER_ABORT.
-  virtual CallbackReturnType operator()(const IterationSummary& summary);
+  CallbackReturnType operator()(const IterationSummary& summary) final;
 
   // Notify this that a gradient error has occurred (thread safe).
   void SetGradientErrorDetected(std::string& error_log);
diff --git a/internal/ceres/gradient_checking_cost_function_test.cc b/internal/ceres/gradient_checking_cost_function_test.cc
index 3747142..ff211ed 100644
--- a/internal/ceres/gradient_checking_cost_function_test.cc
+++ b/internal/ceres/gradient_checking_cost_function_test.cc
@@ -268,9 +268,9 @@
   }
   virtual ~UnaryCostFunction() {}
 
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     for (int i = 0; i < num_residuals(); ++i) {
       residuals[i] = 1;
     }
@@ -289,9 +289,9 @@
     mutable_parameter_block_sizes()->push_back(parameter_block2_size);
   }
 
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     for (int i = 0; i < num_residuals(); ++i) {
       residuals[i] = 2;
     }
@@ -312,9 +312,9 @@
     mutable_parameter_block_sizes()->push_back(parameter_block3_size);
   }
 
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     for (int i = 0; i < num_residuals(); ++i) {
       residuals[i] = 3;
     }
diff --git a/internal/ceres/gradient_problem_evaluator.h b/internal/ceres/gradient_problem_evaluator.h
index 5458631..c5ad1d7 100644
--- a/internal/ceres/gradient_problem_evaluator.h
+++ b/internal/ceres/gradient_problem_evaluator.h
@@ -48,13 +48,13 @@
   explicit GradientProblemEvaluator(const GradientProblem& problem)
       : problem_(problem) {}
   virtual ~GradientProblemEvaluator() {}
-  virtual SparseMatrix* CreateJacobian() const { return NULL; }
-  virtual bool Evaluate(const EvaluateOptions& evaluate_options,
-                        const double* state,
-                        double* cost,
-                        double* residuals,
-                        double* gradient,
-                        SparseMatrix* jacobian) {
+  SparseMatrix* CreateJacobian() const final { return nullptr; }
+  bool Evaluate(const EvaluateOptions& evaluate_options,
+                const double* state,
+                double* cost,
+                double* residuals,
+                double* gradient,
+                SparseMatrix* jacobian) final {
     CHECK(jacobian == NULL);
     ScopedExecutionTimer total_timer("Evaluator::Total", &execution_summary_);
     // The reason we use Residual and Jacobian here even when we are
@@ -70,23 +70,23 @@
     return problem_.Evaluate(state, cost, gradient);
   }
 
-  virtual bool Plus(const double* state,
-                    const double* delta,
-                    double* state_plus_delta) const {
+  bool Plus(const double* state,
+            const double* delta,
+            double* state_plus_delta) const final {
     return problem_.Plus(state, delta, state_plus_delta);
   }
 
-  virtual int NumParameters() const {
+  int NumParameters() const final {
     return problem_.NumParameters();
   }
 
-  virtual int NumEffectiveParameters()  const {
+  int NumEffectiveParameters() const final {
     return problem_.NumLocalParameters();
   }
 
-  virtual int NumResiduals() const { return 1; }
+  int NumResiduals() const final { return 1; }
 
-  virtual std::map<std::string, internal::CallStatistics> Statistics() const {
+  std::map<std::string, internal::CallStatistics> Statistics() const final {
     return execution_summary_.statistics();
   }
 
diff --git a/internal/ceres/gradient_problem_solver_test.cc b/internal/ceres/gradient_problem_solver_test.cc
index 20574de..1a08c48 100644
--- a/internal/ceres/gradient_problem_solver_test.cc
+++ b/internal/ceres/gradient_problem_solver_test.cc
@@ -41,9 +41,9 @@
  public:
   virtual ~Rosenbrock() {}
 
-  virtual bool Evaluate(const double* parameters,
-                        double* cost,
-                        double* gradient) const {
+  bool Evaluate(const double* parameters,
+                double* cost,
+                double* gradient) const final {
     const double x = parameters[0];
     const double y = parameters[1];
 
@@ -55,7 +55,7 @@
     return true;
   }
 
-  virtual int NumParameters() const { return 2; }
+  int NumParameters() const final { return 2; }
 };
 
 TEST(GradientProblemSolver, SolvesRosenbrockWithDefaultOptions) {
@@ -74,9 +74,9 @@
 
 class QuadraticFunction : public ceres::FirstOrderFunction {
   virtual ~QuadraticFunction() {}
-  virtual bool Evaluate(const double* parameters,
-                        double* cost,
-                        double* gradient) const {
+  bool Evaluate(const double* parameters,
+                double* cost,
+                double* gradient) const final {
     const double x = parameters[0];
     *cost = 0.5 * (5.0 - x) * (5.0 - x);
     if (gradient != NULL) {
@@ -85,13 +85,13 @@
 
     return true;
   }
-  virtual int NumParameters() const { return 1; }
+  int NumParameters() const final { return 1; }
 };
 
 struct RememberingCallback : public IterationCallback {
   explicit RememberingCallback(double *x) : calls(0), x(x) {}
   virtual ~RememberingCallback() {}
-  virtual CallbackReturnType operator()(const IterationSummary& summary) {
+  CallbackReturnType operator()(const IterationSummary& summary) final {
     x_values.push_back(*x);
     return SOLVER_CONTINUE;
   }
diff --git a/internal/ceres/gradient_problem_test.cc b/internal/ceres/gradient_problem_test.cc
index b352577..640cf5f 100644
--- a/internal/ceres/gradient_problem_test.cc
+++ b/internal/ceres/gradient_problem_test.cc
@@ -46,9 +46,9 @@
     }
   }
 
-  virtual bool Evaluate(const double* parameters,
-                        double* cost,
-                        double* gradient) const {
+  bool Evaluate(const double* parameters,
+                double* cost,
+                double* gradient) const final {
     const double x = parameters[0];
     cost[0] = x * x;
     if (gradient != NULL) {
@@ -57,7 +57,7 @@
     return true;
   }
 
-  virtual int NumParameters() const { return 1; }
+  int NumParameters() const final { return 1; }
 
  private:
   bool* flag_to_set_on_destruction_;
diff --git a/internal/ceres/implicit_schur_complement.h b/internal/ceres/implicit_schur_complement.h
index 1fac72c..f4ddf72 100644
--- a/internal/ceres/implicit_schur_complement.h
+++ b/internal/ceres/implicit_schur_complement.h
@@ -113,11 +113,11 @@
   void Init(const BlockSparseMatrix& A, const double* D, const double* b);
 
   // y += Sx, where S is the Schur complement.
-  virtual void RightMultiply(const double* x, double* y) const;
+  void RightMultiply(const double* x, double* y) const final;
 
   // The Schur complement is a symmetric positive definite matrix,
   // thus the left and right multiply operators are the same.
-  virtual void LeftMultiply(const double* x, double* y) const {
+  void LeftMultiply(const double* x, double* y) const final {
     RightMultiply(x, y);
   }
 
@@ -127,8 +127,8 @@
   // complement.
   void BackSubstitute(const double* x, double* y);
 
-  virtual int num_rows() const { return A_->num_cols_f(); }
-  virtual int num_cols() const { return A_->num_cols_f(); }
+  int num_rows() const final { return A_->num_cols_f(); }
+  int num_cols() const final { return A_->num_cols_f(); }
   const Vector& rhs()    const { return rhs_;             }
 
   const BlockSparseMatrix* block_diagonal_EtE_inverse() const {
diff --git a/internal/ceres/implicit_schur_complement_test.cc b/internal/ceres/implicit_schur_complement_test.cc
index 3beb386..fb07a52 100644
--- a/internal/ceres/implicit_schur_complement_test.cc
+++ b/internal/ceres/implicit_schur_complement_test.cc
@@ -55,7 +55,7 @@
 
 class ImplicitSchurComplementTest : public ::testing::Test {
  protected :
-  virtual void SetUp() {
+  void SetUp() final {
     std::unique_ptr<LinearLeastSquaresProblem> problem(
         CreateLinearLeastSquaresProblemFromId(2));
 
diff --git a/internal/ceres/iterative_refiner_test.cc b/internal/ceres/iterative_refiner_test.cc
index 7ca0a5e..a557cb5 100644
--- a/internal/ceres/iterative_refiner_test.cc
+++ b/internal/ceres/iterative_refiner_test.cc
@@ -57,27 +57,27 @@
   virtual ~FakeSparseMatrix() {}
 
   // y += Ax
-  virtual void RightMultiply(const double* x, double* y) const {
+  void RightMultiply(const double* x, double* y) const final {
     VectorRef(y, m_.cols()) += m_ * ConstVectorRef(x, m_.cols());
   }
   // y += A'x
-  virtual void LeftMultiply(const double* x, double* y) const {
+  void LeftMultiply(const double* x, double* y) const final {
     // We will assume that this is a symmetric matrix.
     RightMultiply(x, y);
   }
 
-  virtual double* mutable_values() { return m_.data(); }
-  virtual const double* values() const { return m_.data(); }
-  virtual int num_rows() const { return m_.cols(); }
-  virtual int num_cols() const { return m_.cols(); }
-  virtual int num_nonzeros() const { return m_.cols() * m_.cols(); }
+  double* mutable_values() final { return m_.data(); }
+  const double* values() const final { return m_.data(); }
+  int num_rows() const final { return m_.cols(); }
+  int num_cols() const final { return m_.cols(); }
+  int num_nonzeros() const final { return m_.cols() * m_.cols(); }
 
   // The following methods are not needed for tests in this file.
-  virtual void SquaredColumnNorm(double* x) const DO_NOT_CALL;
-  virtual void ScaleColumns(const double* scale) DO_NOT_CALL;
-  virtual void SetZero() DO_NOT_CALL;
-  virtual void ToDenseMatrix(Matrix* dense_matrix) const DO_NOT_CALL;
-  virtual void ToTextFile(FILE* file) const DO_NOT_CALL;
+  void SquaredColumnNorm(double* x) const final DO_NOT_CALL;
+  void ScaleColumns(const double* scale) final DO_NOT_CALL;
+  void SetZero() final DO_NOT_CALL;
+  void ToDenseMatrix(Matrix* dense_matrix) const final DO_NOT_CALL;
+  void ToTextFile(FILE* file) const final DO_NOT_CALL;
 
  private:
   Matrix m_;
@@ -92,9 +92,9 @@
   FakeSparseCholesky(const Matrix& lhs) { lhs_ = lhs.cast<Scalar>(); }
   virtual ~FakeSparseCholesky() {}
 
-  virtual LinearSolverTerminationType Solve(const double* rhs_ptr,
+  LinearSolverTerminationType Solve(const double* rhs_ptr,
                                             double* solution_ptr,
-                                            std::string* message) {
+                                            std::string* message) final {
     const int num_cols = lhs_.cols();
     VectorRef solution(solution_ptr, num_cols);
     ConstVectorRef rhs(rhs_ptr, num_cols);
@@ -103,17 +103,17 @@
   }
 
   // The following methods are not needed for tests in this file.
-  virtual CompressedRowSparseMatrix::StorageType StorageType() const
+  CompressedRowSparseMatrix::StorageType StorageType() const
       DO_NOT_CALL_WITH_RETURN(CompressedRowSparseMatrix::UPPER_TRIANGULAR);
-  virtual LinearSolverTerminationType Factorize(CompressedRowSparseMatrix* lhs,
+  LinearSolverTerminationType Factorize(CompressedRowSparseMatrix* lhs,
                                                 std::string* message)
       DO_NOT_CALL_WITH_RETURN(LINEAR_SOLVER_FAILURE);
 
-  virtual LinearSolverTerminationType FactorAndSolve(
+  LinearSolverTerminationType FactorAndSolve(
       CompressedRowSparseMatrix* lhs,
       const double* rhs,
       double* solution,
-      std::string* message) DO_NOT_CALL_WITH_RETURN(LINEAR_SOLVER_FAILURE);
+      std::string* message) final DO_NOT_CALL_WITH_RETURN(LINEAR_SOLVER_FAILURE);
 
  private:
   Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> lhs_;
diff --git a/internal/ceres/iterative_schur_complement_solver.h b/internal/ceres/iterative_schur_complement_solver.h
index c058f81..9aed94f 100644
--- a/internal/ceres/iterative_schur_complement_solver.h
+++ b/internal/ceres/iterative_schur_complement_solver.h
@@ -76,11 +76,11 @@
   virtual ~IterativeSchurComplementSolver();
 
  private:
-  virtual LinearSolver::Summary SolveImpl(
+  LinearSolver::Summary SolveImpl(
       BlockSparseMatrix* A,
       const double* b,
       const LinearSolver::PerSolveOptions& options,
-      double* x);
+      double* x) final;
 
   void CreatePreconditioner(BlockSparseMatrix* A);
 
diff --git a/internal/ceres/levenberg_marquardt_strategy.h b/internal/ceres/levenberg_marquardt_strategy.h
index c87a016..8fb37f3 100644
--- a/internal/ceres/levenberg_marquardt_strategy.h
+++ b/internal/ceres/levenberg_marquardt_strategy.h
@@ -49,14 +49,14 @@
   virtual ~LevenbergMarquardtStrategy();
 
   // TrustRegionStrategy interface
-  virtual TrustRegionStrategy::Summary ComputeStep(
+  TrustRegionStrategy::Summary ComputeStep(
       const TrustRegionStrategy::PerSolveOptions& per_solve_options,
       SparseMatrix* jacobian,
       const double* residuals,
-      double* step);
-  virtual void StepAccepted(double step_quality);
-  virtual void StepRejected(double step_quality);
-  virtual void StepIsInvalid() {
+      double* step) final;
+  void StepAccepted(double step_quality) final;
+  void StepRejected(double step_quality) final;
+  void StepIsInvalid() final {
     // Treat the current step as a rejected step with no increase in
     // solution quality. Since rejected steps lead to decrease in the
     // size of the trust region, the next time ComputeStep is called,
@@ -64,7 +64,7 @@
     StepRejected(0.0);
   }
 
-  virtual double Radius() const;
+  double Radius() const final;
 
  private:
   LinearSolver* linear_solver_;
diff --git a/internal/ceres/levenberg_marquardt_strategy_test.cc b/internal/ceres/levenberg_marquardt_strategy_test.cc
index cfbec71..f8f06bf 100644
--- a/internal/ceres/levenberg_marquardt_strategy_test.cc
+++ b/internal/ceres/levenberg_marquardt_strategy_test.cc
@@ -61,11 +61,11 @@
   virtual ~RegularizationCheckingLinearSolver() {}
 
  private:
-  virtual LinearSolver::Summary SolveImpl(
+  LinearSolver::Summary SolveImpl(
       DenseSparseMatrix* A,
       const double* b,
       const LinearSolver::PerSolveOptions& per_solve_options,
-      double* x) {
+      double* x) final {
     CHECK(per_solve_options.D != nullptr);
     for (int i = 0; i < num_cols_; ++i) {
       EXPECT_NEAR(per_solve_options.D[i], diagonal_[i], kTolerance)
diff --git a/internal/ceres/line_search.h b/internal/ceres/line_search.h
index a162979..d59fd77 100644
--- a/internal/ceres/line_search.h
+++ b/internal/ceres/line_search.h
@@ -262,10 +262,10 @@
   virtual ~ArmijoLineSearch() {}
 
  private:
-  virtual void DoSearch(double step_size_estimate,
-                        double initial_cost,
-                        double initial_gradient,
-                        Summary* summary) const;
+  void DoSearch(double step_size_estimate,
+                double initial_cost,
+                double initial_gradient,
+                Summary* summary) const final;
 };
 
 // Bracketing / Zoom Strong Wolfe condition line search.  This implementation
@@ -295,10 +295,10 @@
                  Summary* summary) const;
 
  private:
-  virtual void DoSearch(double step_size_estimate,
-                        double initial_cost,
-                        double initial_gradient,
-                        Summary* summary) const;
+  void DoSearch(double step_size_estimate,
+                double initial_cost,
+                double initial_gradient,
+                Summary* summary) const final;
 };
 
 }  // namespace internal
diff --git a/internal/ceres/line_search_minimizer.h b/internal/ceres/line_search_minimizer.h
index 54b7202..191128a 100644
--- a/internal/ceres/line_search_minimizer.h
+++ b/internal/ceres/line_search_minimizer.h
@@ -66,9 +66,9 @@
   };
 
   ~LineSearchMinimizer() {}
-  virtual void Minimize(const Minimizer::Options& options,
-                        double* parameters,
-                        Solver::Summary* summary);
+  void Minimize(const Minimizer::Options& options,
+                double* parameters,
+                Solver::Summary* summary) final;
 };
 
 }  // namespace internal
diff --git a/internal/ceres/line_search_minimizer_test.cc b/internal/ceres/line_search_minimizer_test.cc
index aa83769..86623b0 100644
--- a/internal/ceres/line_search_minimizer_test.cc
+++ b/internal/ceres/line_search_minimizer_test.cc
@@ -40,9 +40,9 @@
 
 class QuadraticFirstOrderFunction : public ceres::FirstOrderFunction {
  public:
-  virtual bool Evaluate(const double* parameters,
-                        double* cost,
-                        double* gradient) const {
+  bool Evaluate(const double* parameters,
+                double* cost,
+                double* gradient) const final {
 
     cost[0] = parameters[0] * parameters[0];
     if (gradient != NULL) {
@@ -51,7 +51,7 @@
     return true;
   }
 
-  virtual int NumParameters() const { return 1; }
+  int NumParameters() const final { return 1; }
 };
 
 TEST(LineSearchMinimizerTest, FinalCostIsZero) {
diff --git a/internal/ceres/line_search_preprocessor.h b/internal/ceres/line_search_preprocessor.h
index 132d83a..12ccb53 100644
--- a/internal/ceres/line_search_preprocessor.h
+++ b/internal/ceres/line_search_preprocessor.h
@@ -39,9 +39,9 @@
 class LineSearchPreprocessor : public Preprocessor {
  public:
   virtual ~LineSearchPreprocessor();
-  virtual bool Preprocess(const Solver::Options& options,
-                          ProblemImpl* problem,
-                          PreprocessedProblem* preprocessed_problem);
+  bool Preprocess(const Solver::Options& options,
+                  ProblemImpl* problem,
+                  PreprocessedProblem* preprocessed_problem) final;
 };
 
 }  // namespace internal
diff --git a/internal/ceres/local_parameterization_test.cc b/internal/ceres/local_parameterization_test.cc
index a2eff2f..336474c 100644
--- a/internal/ceres/local_parameterization_test.cc
+++ b/internal/ceres/local_parameterization_test.cc
@@ -583,7 +583,7 @@
 
 class ProductParameterizationTest : public ::testing::Test {
  protected :
-  virtual void SetUp() {
+  void SetUp() final {
     const int global_size1 = 5;
     std::vector<int> constant_parameters1;
     constant_parameters1.push_back(2);
diff --git a/internal/ceres/low_rank_inverse_hessian.h b/internal/ceres/low_rank_inverse_hessian.h
index 0ee80d0..0028a98 100644
--- a/internal/ceres/low_rank_inverse_hessian.h
+++ b/internal/ceres/low_rank_inverse_hessian.h
@@ -84,12 +84,12 @@
   bool Update(const Vector& delta_x, const Vector& delta_gradient);
 
   // LinearOperator interface
-  virtual void RightMultiply(const double* x, double* y) const;
-  virtual void LeftMultiply(const double* x, double* y) const {
+  void RightMultiply(const double* x, double* y) const final;
+  void LeftMultiply(const double* x, double* y) const final {
     RightMultiply(x, y);
   }
-  virtual int num_rows() const { return num_parameters_; }
-  virtual int num_cols() const { return num_parameters_; }
+  int num_rows() const final { return num_parameters_; }
+  int num_cols() const final { return num_parameters_; }
 
  private:
   const int num_parameters_;
diff --git a/internal/ceres/minimizer_test.cc b/internal/ceres/minimizer_test.cc
index fe9b15e..b0a2d96 100644
--- a/internal/ceres/minimizer_test.cc
+++ b/internal/ceres/minimizer_test.cc
@@ -39,7 +39,7 @@
 class FakeIterationCallback : public IterationCallback {
  public:
   virtual ~FakeIterationCallback() {}
-  virtual CallbackReturnType operator()(const IterationSummary& summary) {
+  CallbackReturnType operator()(const IterationSummary& summary) final {
     return SOLVER_CONTINUE;
   }
 };
@@ -62,7 +62,7 @@
 class AbortingIterationCallback : public IterationCallback {
  public:
   virtual ~AbortingIterationCallback() {}
-  virtual CallbackReturnType operator()(const IterationSummary& summary) {
+  CallbackReturnType operator()(const IterationSummary& summary) final {
     return SOLVER_ABORT;
   }
 };
@@ -80,7 +80,7 @@
 class SucceedingIterationCallback : public IterationCallback {
  public:
   virtual ~SucceedingIterationCallback() {}
-  virtual CallbackReturnType operator()(const IterationSummary& summary) {
+  CallbackReturnType operator()(const IterationSummary& summary) final {
     return SOLVER_TERMINATE_SUCCESSFULLY;
   }
 };
diff --git a/internal/ceres/numeric_diff_cost_function_test.cc b/internal/ceres/numeric_diff_cost_function_test.cc
index 105bef5..20cf1b2 100644
--- a/internal/ceres/numeric_diff_cost_function_test.cc
+++ b/internal/ceres/numeric_diff_cost_function_test.cc
@@ -225,9 +225,9 @@
 template<int num_rows, int num_cols>
 class SizeTestingCostFunction : public SizedCostFunction<num_rows, num_cols> {
  public:
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     return true;
   }
 };
diff --git a/internal/ceres/numeric_diff_test_utils.h b/internal/ceres/numeric_diff_test_utils.h
index 2a551d3..0eddebb 100644
--- a/internal/ceres/numeric_diff_test_utils.h
+++ b/internal/ceres/numeric_diff_test_utils.h
@@ -57,9 +57,9 @@
 
 class EasyCostFunction : public SizedCostFunction<3, 5, 5> {
  public:
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** /* not used */) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** /* not used */) const final {
     return functor_(parameters[0], parameters[1], residuals);
   }
 
@@ -82,9 +82,9 @@
 
 class TranscendentalCostFunction : public SizedCostFunction<2, 5, 5> {
  public:
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** /* not used */) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** /* not used */) const final {
     return functor_(parameters[0], parameters[1], residuals);
   }
  private:
@@ -101,9 +101,9 @@
 
 class ExponentialCostFunction : public SizedCostFunction<1, 1> {
  public:
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** /* not used */) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** /* not used */) const final {
     return functor_(parameters[0], residuals);
   }
 
@@ -135,9 +135,9 @@
       : functor_(noise_factor, random_seed) {
   }
 
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** /* not used */) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** /* not used */) const final {
     return functor_(parameters[0], residuals);
   }
 
diff --git a/internal/ceres/parameter_block_ordering_test.cc b/internal/ceres/parameter_block_ordering_test.cc
index ba61be6..24dfdc9 100644
--- a/internal/ceres/parameter_block_ordering_test.cc
+++ b/internal/ceres/parameter_block_ordering_test.cc
@@ -53,16 +53,16 @@
 
 template <int M, int... Ns>
 class DummyCostFunction : public SizedCostFunction<M, Ns...> {
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     return true;
   }
 };
 
 class SchurOrderingTest : public ::testing::Test {
  protected :
-  virtual void SetUp() {
+  void SetUp() final {
     // The explicit calls to AddParameterBlock are necessary because
     // the below tests depend on the specific numbering of the
     // parameter blocks.
diff --git a/internal/ceres/parameter_block_test.cc b/internal/ceres/parameter_block_test.cc
index e33db48..babd354 100644
--- a/internal/ceres/parameter_block_test.cc
+++ b/internal/ceres/parameter_block_test.cc
@@ -131,20 +131,20 @@
 struct TestParameterization : public LocalParameterization {
  public:
   virtual ~TestParameterization() {}
-  virtual bool Plus(const double* x,
-                    const double* delta,
-                    double* x_plus_delta) const {
+  bool Plus(const double* x,
+            const double* delta,
+            double* x_plus_delta) const final {
     LOG(FATAL) << "Shouldn't get called.";
     return true;
   }
-  virtual bool ComputeJacobian(const double* x,
-                               double* jacobian) const {
+  bool ComputeJacobian(const double* x,
+                       double* jacobian) const final {
     jacobian[0] = *x * 2;
     return true;
   }
 
-  virtual int GlobalSize() const { return 1; }
-  virtual int LocalSize() const { return 1; }
+  int GlobalSize() const final { return 1; }
+  int LocalSize() const final { return 1; }
 };
 
 TEST(ParameterBlock, SetStateUpdatesLocalParameterizationJacobian) {
@@ -178,14 +178,14 @@
   }
 
   virtual ~BadLocalParameterization() {}
-  virtual bool Plus(const double* x,
-                    const double* delta,
-                    double* x_plus_delta) const {
+  bool Plus(const double* x,
+            const double* delta,
+            double* x_plus_delta) const final {
     *x_plus_delta = *x + *delta;
     return true;
   }
 
-  virtual bool ComputeJacobian(const double* x, double* jacobian) const {
+  bool ComputeJacobian(const double* x, double* jacobian) const final {
     if (calls_ == 0) {
       jacobian[0] = 0;
     }
@@ -193,8 +193,8 @@
     return true;
   }
 
-  virtual int GlobalSize() const { return 1;}
-  virtual int LocalSize()  const { return 1;}
+  int GlobalSize() const final { return 1;}
+  int LocalSize()  const final { return 1;}
 
  private:
   mutable int calls_;
diff --git a/internal/ceres/partitioned_matrix_view.h b/internal/ceres/partitioned_matrix_view.h
index 6e75060..3853ea1 100644
--- a/internal/ceres/partitioned_matrix_view.h
+++ b/internal/ceres/partitioned_matrix_view.h
@@ -119,20 +119,20 @@
   PartitionedMatrixView(const BlockSparseMatrix& matrix, int num_col_blocks_e);
 
   virtual ~PartitionedMatrixView();
-  virtual void LeftMultiplyE(const double* x, double* y) const;
-  virtual void LeftMultiplyF(const double* x, double* y) const;
-  virtual void RightMultiplyE(const double* x, double* y) const;
-  virtual void RightMultiplyF(const double* x, double* y) const;
-  virtual BlockSparseMatrix* CreateBlockDiagonalEtE() const;
-  virtual BlockSparseMatrix* CreateBlockDiagonalFtF() const;
-  virtual void UpdateBlockDiagonalEtE(BlockSparseMatrix* block_diagonal) const;
-  virtual void UpdateBlockDiagonalFtF(BlockSparseMatrix* block_diagonal) const;
-  virtual int num_col_blocks_e() const { return num_col_blocks_e_;  }
-  virtual int num_col_blocks_f() const { return num_col_blocks_f_;  }
-  virtual int num_cols_e()       const { return num_cols_e_;        }
-  virtual int num_cols_f()       const { return num_cols_f_;        }
-  virtual int num_rows()         const { return matrix_.num_rows(); }
-  virtual int num_cols()         const { return matrix_.num_cols(); }
+  void LeftMultiplyE(const double* x, double* y) const final;
+  void LeftMultiplyF(const double* x, double* y) const final;
+  void RightMultiplyE(const double* x, double* y) const final;
+  void RightMultiplyF(const double* x, double* y) const final;
+  BlockSparseMatrix* CreateBlockDiagonalEtE() const final;
+  BlockSparseMatrix* CreateBlockDiagonalFtF() const final;
+  void UpdateBlockDiagonalEtE(BlockSparseMatrix* block_diagonal) const final;
+  void UpdateBlockDiagonalFtF(BlockSparseMatrix* block_diagonal) const final;
+  int num_col_blocks_e() const final { return num_col_blocks_e_;  }
+  int num_col_blocks_f() const final { return num_col_blocks_f_;  }
+  int num_cols_e()       const final { return num_cols_e_;        }
+  int num_cols_f()       const final { return num_cols_f_;        }
+  int num_rows()         const final { return matrix_.num_rows(); }
+  int num_cols()         const final { return matrix_.num_cols(); }
 
  private:
   BlockSparseMatrix* CreateBlockDiagonalMatrixLayout(int start_col_block,
diff --git a/internal/ceres/partitioned_matrix_view_test.cc b/internal/ceres/partitioned_matrix_view_test.cc
index 40b49ef..827cfb7 100644
--- a/internal/ceres/partitioned_matrix_view_test.cc
+++ b/internal/ceres/partitioned_matrix_view_test.cc
@@ -48,7 +48,7 @@
 
 class PartitionedMatrixViewTest : public ::testing::Test {
  protected :
-  virtual void SetUp() {
+  void SetUp() final {
     srand(5);
     std::unique_ptr<LinearLeastSquaresProblem> problem(
         CreateLinearLeastSquaresProblemFromId(2));
diff --git a/internal/ceres/preconditioner.h b/internal/ceres/preconditioner.h
index 476697d..3e46ed8 100644
--- a/internal/ceres/preconditioner.h
+++ b/internal/ceres/preconditioner.h
@@ -131,13 +131,13 @@
   // LeftMultiply and num_cols are just calls to RightMultiply and
   // num_rows respectively. Update() must be called before
   // RightMultiply can be called.
-  virtual void RightMultiply(const double* x, double* y) const = 0;
-  virtual void LeftMultiply(const double* x, double* y) const {
+  void RightMultiply(const double* x, double* y) const override = 0;
+  void LeftMultiply(const double* x, double* y) const override {
     return RightMultiply(x, y);
   }
 
-  virtual int num_rows() const = 0;
-  virtual int num_cols() const {
+  int num_rows() const override = 0;
+  int num_cols() const override {
     return num_rows();
   }
 };
@@ -149,7 +149,7 @@
 class TypedPreconditioner : public Preconditioner {
  public:
   virtual ~TypedPreconditioner() {}
-  virtual bool Update(const LinearOperator& A, const double* D) {
+  bool Update(const LinearOperator& A, const double* D) final {
     return UpdateImpl(*down_cast<const MatrixType*>(&A), D);
   }
 
diff --git a/internal/ceres/problem_test.cc b/internal/ceres/problem_test.cc
index 986d13d..038600c 100644
--- a/internal/ceres/problem_test.cc
+++ b/internal/ceres/problem_test.cc
@@ -65,11 +65,12 @@
     set_num_residuals(num_residuals);
     mutable_parameter_block_sizes()->push_back(parameter_block_size);
   }
+
   virtual ~UnaryCostFunction() {}
 
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     for (int i = 0; i < num_residuals(); ++i) {
       residuals[i] = 1;
     }
@@ -88,9 +89,9 @@
     mutable_parameter_block_sizes()->push_back(parameter_block2_size);
   }
 
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     for (int i = 0; i < num_residuals(); ++i) {
       residuals[i] = 2;
     }
@@ -111,9 +112,9 @@
     mutable_parameter_block_sizes()->push_back(parameter_block3_size);
   }
 
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     for (int i = 0; i < num_residuals(); ++i) {
       residuals[i] = 3;
     }
@@ -315,9 +316,9 @@
     *num_destructions_ += 1;
   }
 
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     return true;
   }
 
@@ -1071,9 +1072,9 @@
     }
   }
 
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     for (int i = 0; i < kNumResiduals; ++i) {
       residuals[i] = i;
       for (int j = 0; j < kNumParameterBlocks; ++j) {
diff --git a/internal/ceres/program_evaluator.h b/internal/ceres/program_evaluator.h
index 6781eb7..4e174eb 100644
--- a/internal/ceres/program_evaluator.h
+++ b/internal/ceres/program_evaluator.h
@@ -131,7 +131,7 @@
   }
 
   // Implementation of Evaluator interface.
-  SparseMatrix* CreateJacobian() const {
+  SparseMatrix* CreateJacobian() const final {
     return jacobian_writer_.CreateJacobian();
   }
 
@@ -140,7 +140,7 @@
                 double* cost,
                 double* residuals,
                 double* gradient,
-                SparseMatrix* jacobian) {
+                SparseMatrix* jacobian) final {
     ScopedExecutionTimer total_timer("Evaluator::Total", &execution_summary_);
     ScopedExecutionTimer call_type_timer(gradient == NULL && jacobian == NULL
                                          ? "Evaluator::Residual"
@@ -287,22 +287,22 @@
 
   bool Plus(const double* state,
             const double* delta,
-            double* state_plus_delta) const {
+            double* state_plus_delta) const final {
     return program_->Plus(state, delta, state_plus_delta);
   }
 
-  int NumParameters() const {
+  int NumParameters() const final {
     return program_->NumParameters();
   }
-  int NumEffectiveParameters() const {
+  int NumEffectiveParameters() const final {
     return program_->NumEffectiveParameters();
   }
 
-  int NumResiduals() const {
+  int NumResiduals() const final {
     return program_->NumResiduals();
   }
 
-  virtual std::map<std::string, CallStatistics> Statistics() const {
+  std::map<std::string, CallStatistics> Statistics() const final {
     return execution_summary_.statistics();
   }
 
diff --git a/internal/ceres/program_test.cc b/internal/ceres/program_test.cc
index 99379c0..74dcd75 100644
--- a/internal/ceres/program_test.cc
+++ b/internal/ceres/program_test.cc
@@ -51,9 +51,9 @@
 // A cost function that simply returns its argument.
 class UnaryIdentityCostFunction : public SizedCostFunction<1, 1> {
  public:
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     residuals[0] = parameters[0][0];
     if (jacobians != nullptr && jacobians[0] != nullptr) {
       jacobians[0][0] = 1.0;
@@ -66,9 +66,9 @@
 template <int kNumResiduals, int... Ns>
 class MockCostFunctionBase : public SizedCostFunction<kNumResiduals, Ns...> {
  public:
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     const int kNumParameters = Sum<integer_sequence<int, Ns...>>::Value;
 
     for (int i = 0; i < kNumResiduals; ++i) {
@@ -339,9 +339,9 @@
   virtual ~NumParameterBlocksCostFunction() {
   }
 
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     return true;
   }
 };
diff --git a/internal/ceres/reorder_program_test.cc b/internal/ceres/reorder_program_test.cc
index f7f67aa..2cfc123 100644
--- a/internal/ceres/reorder_program_test.cc
+++ b/internal/ceres/reorder_program_test.cc
@@ -48,9 +48,9 @@
 template <int kNumResiduals, int... Ns>
 class MockCostFunctionBase : public SizedCostFunction<kNumResiduals, Ns...> {
  public:
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     // Do nothing. This is never called.
     return true;
   }
diff --git a/internal/ceres/residual_block_test.cc b/internal/ceres/residual_block_test.cc
index 3a33be7..482e7ce 100644
--- a/internal/ceres/residual_block_test.cc
+++ b/internal/ceres/residual_block_test.cc
@@ -55,9 +55,9 @@
     mutable_parameter_block_sizes()->push_back(parameter_block3_size);
   }
 
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     for (int i = 0; i < num_residuals(); ++i) {
       residuals[i] = i;
     }
@@ -170,9 +170,9 @@
 // Trivial cost function that accepts three arguments.
 class LocallyParameterizedCostFunction: public SizedCostFunction<3, 2, 3, 4> {
  public:
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     for (int i = 0; i < num_residuals(); ++i) {
       residuals[i] = i;
     }
diff --git a/internal/ceres/residual_block_utils_test.cc b/internal/ceres/residual_block_utils_test.cc
index deaa13a..6ad3729 100644
--- a/internal/ceres/residual_block_utils_test.cc
+++ b/internal/ceres/residual_block_utils_test.cc
@@ -73,9 +73,9 @@
 // valid residuals and jacobians.
 class GoodCostFunction: public SizedCostFunction<1, 1> {
  public:
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     residuals[0] = 1;
     if (jacobians != NULL && jacobians[0] != NULL) {
       jacobians[0][0] = 0.0;
@@ -88,9 +88,9 @@
 // which user code can cause ResidualBlock::Evaluate to fail.
 class NoResidualUpdateCostFunction: public SizedCostFunction<1, 1> {
  public:
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     // Forget to update the residuals.
     // residuals[0] = 1;
     if (jacobians != NULL && jacobians[0] != NULL) {
@@ -102,9 +102,9 @@
 
 class NoJacobianUpdateCostFunction: public SizedCostFunction<1, 1> {
  public:
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     residuals[0] = 1;
     if (jacobians != NULL && jacobians[0] != NULL) {
       // Forget to update the jacobians.
@@ -116,9 +116,9 @@
 
 class BadResidualCostFunction: public SizedCostFunction<1, 1> {
  public:
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     residuals[0] = std::numeric_limits<double>::infinity();
     if (jacobians != NULL && jacobians[0] != NULL) {
       jacobians[0][0] = 0.0;
@@ -129,9 +129,9 @@
 
 class BadJacobianCostFunction: public SizedCostFunction<1, 1> {
  public:
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     residuals[0] = 1.0;
     if (jacobians != NULL && jacobians[0] != NULL) {
       jacobians[0][0] = std::numeric_limits<double>::quiet_NaN();
diff --git a/internal/ceres/schur_complement_solver.cc b/internal/ceres/schur_complement_solver.cc
index 19f5b06..a80bd23 100644
--- a/internal/ceres/schur_complement_solver.cc
+++ b/internal/ceres/schur_complement_solver.cc
@@ -73,17 +73,17 @@
   virtual ~BlockRandomAccessSparseMatrixAdapter() {}
 
   // y = y + Ax;
-  virtual void RightMultiply(const double* x, double* y) const {
+  void RightMultiply(const double* x, double* y) const final {
     m_.SymmetricRightMultiply(x, y);
   }
 
   // y = y + A'x;
-  virtual void LeftMultiply(const double* x, double* y) const {
+  void LeftMultiply(const double* x, double* y) const final {
     m_.SymmetricRightMultiply(x, y);
   }
 
-  virtual int num_rows() const { return m_.num_rows(); }
-  virtual int num_cols() const { return m_.num_rows(); }
+  int num_rows() const final { return m_.num_rows(); }
+  int num_cols() const final { return m_.num_rows(); }
 
  private:
   const BlockRandomAccessSparseMatrix& m_;
@@ -99,17 +99,17 @@
   virtual ~BlockRandomAccessDiagonalMatrixAdapter() {}
 
   // y = y + Ax;
-  virtual void RightMultiply(const double* x, double* y) const {
+  void RightMultiply(const double* x, double* y) const final {
     m_.RightMultiply(x, y);
   }
 
   // y = y + A'x;
-  virtual void LeftMultiply(const double* x, double* y) const {
+  void LeftMultiply(const double* x, double* y) const final {
     m_.RightMultiply(x, y);
   }
 
-  virtual int num_rows() const { return m_.num_rows(); }
-  virtual int num_cols() const { return m_.num_rows(); }
+  int num_rows() const final { return m_.num_rows(); }
+  int num_cols() const final { return m_.num_rows(); }
 
  private:
   const BlockRandomAccessDiagonalMatrix& m_;
diff --git a/internal/ceres/schur_complement_solver.h b/internal/ceres/schur_complement_solver.h
index 16ffb8c..87f0478 100644
--- a/internal/ceres/schur_complement_solver.h
+++ b/internal/ceres/schur_complement_solver.h
@@ -120,11 +120,11 @@
 
   // LinearSolver methods
   virtual ~SchurComplementSolver() {}
-  virtual LinearSolver::Summary SolveImpl(
+  LinearSolver::Summary SolveImpl(
       BlockSparseMatrix* A,
       const double* b,
       const LinearSolver::PerSolveOptions& per_solve_options,
-      double* x);
+      double* x) override;
 
  protected:
   const LinearSolver::Options& options() const { return options_; }
@@ -158,10 +158,10 @@
   virtual ~DenseSchurComplementSolver() {}
 
  private:
-  virtual void InitStorage(const CompressedRowBlockStructure* bs);
-  virtual LinearSolver::Summary SolveReducedLinearSystem(
+  void InitStorage(const CompressedRowBlockStructure* bs) final;
+  LinearSolver::Summary SolveReducedLinearSystem(
       const LinearSolver::PerSolveOptions& per_solve_options,
-      double* solution);
+      double* solution) final;
 };
 
 // Sparse Cholesky factorization based solver.
@@ -174,10 +174,10 @@
   virtual ~SparseSchurComplementSolver();
 
  private:
-  virtual void InitStorage(const CompressedRowBlockStructure* bs);
-  virtual LinearSolver::Summary SolveReducedLinearSystem(
+  void InitStorage(const CompressedRowBlockStructure* bs) final;
+  LinearSolver::Summary SolveReducedLinearSystem(
       const LinearSolver::PerSolveOptions& per_solve_options,
-      double* solution);
+      double* solution) final;
   LinearSolver::Summary SolveReducedLinearSystemUsingConjugateGradients(
       const LinearSolver::PerSolveOptions& per_solve_options,
       double* solution);
diff --git a/internal/ceres/schur_eliminator.h b/internal/ceres/schur_eliminator.h
index 11e6eba..52e3535 100644
--- a/internal/ceres/schur_eliminator.h
+++ b/internal/ceres/schur_eliminator.h
@@ -231,19 +231,19 @@
 
   // SchurEliminatorBase Interface
   virtual ~SchurEliminator();
-  virtual void Init(int num_eliminate_blocks,
-                    bool assume_full_rank_ete,
-                    const CompressedRowBlockStructure* bs);
-  virtual void Eliminate(const BlockSparseMatrix* A,
-                         const double* b,
-                         const double* D,
-                         BlockRandomAccessMatrix* lhs,
-                         double* rhs);
-  virtual void BackSubstitute(const BlockSparseMatrix* A,
-                              const double* b,
-                              const double* D,
-                              const double* z,
-                              double* y);
+  void Init(int num_eliminate_blocks,
+            bool assume_full_rank_ete,
+            const CompressedRowBlockStructure* bs) final;
+  void Eliminate(const BlockSparseMatrix* A,
+                 const double* b,
+                 const double* D,
+                 BlockRandomAccessMatrix* lhs,
+                 double* rhs) final;
+  void BackSubstitute(const BlockSparseMatrix* A,
+                      const double* b,
+                      const double* D,
+                      const double* z,
+                      double* y) final;
 
  private:
   // Chunk objects store combinatorial information needed to
diff --git a/internal/ceres/schur_jacobi_preconditioner.h b/internal/ceres/schur_jacobi_preconditioner.h
index c95468f..372b790 100644
--- a/internal/ceres/schur_jacobi_preconditioner.h
+++ b/internal/ceres/schur_jacobi_preconditioner.h
@@ -88,12 +88,12 @@
   virtual ~SchurJacobiPreconditioner();
 
   // Preconditioner interface.
-  virtual void RightMultiply(const double* x, double* y) const;
-  virtual int num_rows() const;
+  void RightMultiply(const double* x, double* y) const final;
+  int num_rows() const final;
 
  private:
   void InitEliminator(const CompressedRowBlockStructure& bs);
-  virtual bool UpdateImpl(const BlockSparseMatrix& A, const double* D);
+  bool UpdateImpl(const BlockSparseMatrix& A, const double* D) final;
 
   Preconditioner::Options options_;
   std::unique_ptr<SchurEliminatorBase> eliminator_;
diff --git a/internal/ceres/solver_test.cc b/internal/ceres/solver_test.cc
index 02494de..601c1e4 100644
--- a/internal/ceres/solver_test.cc
+++ b/internal/ceres/solver_test.cc
@@ -76,7 +76,7 @@
 struct RememberingCallback : public IterationCallback {
   explicit RememberingCallback(double *x) : calls(0), x(x) {}
   virtual ~RememberingCallback() {}
-  virtual CallbackReturnType operator()(const IterationSummary& summary) {
+  CallbackReturnType operator()(const IterationSummary& summary) final {
     x_values.push_back(*x);
     return SOLVER_CONTINUE;
   }
@@ -87,8 +87,8 @@
 
 struct NoOpEvaluationCallback : EvaluationCallback {
   virtual ~NoOpEvaluationCallback() {}
-  virtual void PrepareForEvaluation(bool evaluate_jacobians,
-                                    bool new_evaluation_point) {
+  void PrepareForEvaluation(bool evaluate_jacobians,
+                            bool new_evaluation_point) final {
     (void) evaluate_jacobians;
     (void) new_evaluation_point;
   }
@@ -225,9 +225,9 @@
 // A cost function that simply returns its argument.
 class UnaryIdentityCostFunction : public SizedCostFunction<1, 1> {
  public:
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     residuals[0] = parameters[0][0];
     if (jacobians != nullptr && jacobians[0] != nullptr) {
       jacobians[0][0] = 1.0;
diff --git a/internal/ceres/sparse_normal_cholesky_solver.h b/internal/ceres/sparse_normal_cholesky_solver.h
index 95d5436..cbff2bd 100644
--- a/internal/ceres/sparse_normal_cholesky_solver.h
+++ b/internal/ceres/sparse_normal_cholesky_solver.h
@@ -58,11 +58,11 @@
   virtual ~SparseNormalCholeskySolver();
 
  private:
-  virtual LinearSolver::Summary SolveImpl(
+  LinearSolver::Summary SolveImpl(
       BlockSparseMatrix* A,
       const double* b,
       const LinearSolver::PerSolveOptions& options,
-      double* x);
+      double* x) final;
 
   const LinearSolver::Options options_;
   Vector rhs_;
diff --git a/internal/ceres/sparse_normal_cholesky_solver_test.cc b/internal/ceres/sparse_normal_cholesky_solver_test.cc
index c4b4a0b..10f898b 100644
--- a/internal/ceres/sparse_normal_cholesky_solver_test.cc
+++ b/internal/ceres/sparse_normal_cholesky_solver_test.cc
@@ -53,7 +53,7 @@
 // classes.
 class SparseNormalCholeskySolverTest : public ::testing::Test {
  protected:
-  virtual void SetUp() {
+  void SetUp() final {
     std::unique_ptr<LinearLeastSquaresProblem> problem(
         CreateLinearLeastSquaresProblemFromId(2));
 
diff --git a/internal/ceres/subset_preconditioner.h b/internal/ceres/subset_preconditioner.h
index afd3704..6f3c9ec 100644
--- a/internal/ceres/subset_preconditioner.h
+++ b/internal/ceres/subset_preconditioner.h
@@ -72,12 +72,12 @@
   virtual ~SubsetPreconditioner();
 
   // Preconditioner interface
-  virtual void RightMultiply(const double* x, double* y) const;
-  virtual int num_rows() const { return num_cols_; }
-  virtual int num_cols() const { return num_cols_; }
+  void RightMultiply(const double* x, double* y) const final;
+  int num_rows() const final { return num_cols_; }
+  int num_cols() const final { return num_cols_; }
 
  private:
-  virtual bool UpdateImpl(const BlockSparseMatrix& A, const double* D);
+  bool UpdateImpl(const BlockSparseMatrix& A, const double* D) final;
 
   const Preconditioner::Options options_;
   const int num_cols_;
diff --git a/internal/ceres/subset_preconditioner_test.cc b/internal/ceres/subset_preconditioner_test.cc
index 5466f1b..ec0ea9a 100644
--- a/internal/ceres/subset_preconditioner_test.cc
+++ b/internal/ceres/subset_preconditioner_test.cc
@@ -88,7 +88,7 @@
 
 class SubsetPreconditionerTest : public ::testing::TestWithParam<Param> {
  protected:
-  virtual void SetUp() {
+  void SetUp() final {
     BlockSparseMatrix::RandomMatrixOptions options;
     options.num_col_blocks = 4;
     options.min_col_block_size = 1;
diff --git a/internal/ceres/suitesparse.h b/internal/ceres/suitesparse.h
index 7770d9e..b77b296 100644
--- a/internal/ceres/suitesparse.h
+++ b/internal/ceres/suitesparse.h
@@ -290,12 +290,12 @@
 
   // SparseCholesky interface.
   virtual ~SuiteSparseCholesky();
-  virtual CompressedRowSparseMatrix::StorageType StorageType() const;
-  virtual LinearSolverTerminationType Factorize(
-      CompressedRowSparseMatrix* lhs, std::string* message);
-  virtual LinearSolverTerminationType Solve(const double* rhs,
-                                            double* solution,
-                                            std::string* message);
+  CompressedRowSparseMatrix::StorageType StorageType() const final;
+  LinearSolverTerminationType Factorize(
+      CompressedRowSparseMatrix* lhs, std::string* message) final;
+  LinearSolverTerminationType Solve(const double* rhs,
+                                    double* solution,
+                                    std::string* message) final;
  private:
   SuiteSparseCholesky(const OrderingType ordering_type);
 
diff --git a/internal/ceres/test_util.h b/internal/ceres/test_util.h
index e43eb35..b5f1393 100644
--- a/internal/ceres/test_util.h
+++ b/internal/ceres/test_util.h
@@ -80,7 +80,7 @@
 template <typename SystemTestProblem>
 class SystemTest : public ::testing::Test {
  protected:
-  virtual void SetUp() {
+  void SetUp() final {
     SystemTestProblem system_test_problem;
     SolveAndEvaluateFinalResiduals(
         *system_test_problem.mutable_solver_options(),
diff --git a/internal/ceres/tiny_solver_cost_function_adapter_test.cc b/internal/ceres/tiny_solver_cost_function_adapter_test.cc
index 620df41..13ad406 100644
--- a/internal/ceres/tiny_solver_cost_function_adapter_test.cc
+++ b/internal/ceres/tiny_solver_cost_function_adapter_test.cc
@@ -41,9 +41,9 @@
 namespace ceres {
 
 class CostFunction2x3 : public SizedCostFunction<2,3> {
-  virtual bool Evaluate(double const* const* parameters,
-                        double* residuals,
-                        double** jacobians) const {
+  bool Evaluate(double const* const* parameters,
+                double* residuals,
+                double** jacobians) const final {
     double x = parameters[0][0];
     double y = parameters[0][1];
     double z = parameters[0][2];
diff --git a/internal/ceres/triplet_sparse_matrix.h b/internal/ceres/triplet_sparse_matrix.h
index 606f8e8..2ee0fa9 100644
--- a/internal/ceres/triplet_sparse_matrix.h
+++ b/internal/ceres/triplet_sparse_matrix.h
@@ -58,22 +58,22 @@
 
   TripletSparseMatrix& operator=(const TripletSparseMatrix& rhs);
 
-  ~TripletSparseMatrix();
+  virtual ~TripletSparseMatrix();
 
   // Implementation of the SparseMatrix interface.
-  virtual void SetZero();
-  virtual void RightMultiply(const double* x, double* y) const;
-  virtual void LeftMultiply(const double* x, double* y) const;
-  virtual void SquaredColumnNorm(double* x) const;
-  virtual void ScaleColumns(const double* scale);
-  virtual void ToDenseMatrix(Matrix* dense_matrix) const;
-  virtual void ToTextFile(FILE* file) const;
-  virtual int num_rows()        const { return num_rows_;     }
-  virtual int num_cols()        const { return num_cols_;     }
-  virtual int num_nonzeros()    const { return num_nonzeros_; }
-  virtual const double* values()  const { return values_.get(); }
-  virtual double* mutable_values()      { return values_.get(); }
-  virtual void set_num_nonzeros(int num_nonzeros);
+  void SetZero() final;
+  void RightMultiply(const double* x, double* y) const final;
+  void LeftMultiply(const double* x, double* y) const final;
+  void SquaredColumnNorm(double* x) const final;
+  void ScaleColumns(const double* scale) final;
+  void ToDenseMatrix(Matrix* dense_matrix) const final;
+  void ToTextFile(FILE* file) const final;
+  int num_rows()        const final   { return num_rows_;     }
+  int num_cols()        const final   { return num_cols_;     }
+  int num_nonzeros()    const final   { return num_nonzeros_; }
+  const double* values()  const final { return values_.get(); }
+  double* mutable_values() final      { return values_.get(); }
+  void set_num_nonzeros(int num_nonzeros);
 
   // Increase max_num_nonzeros and correspondingly increase the size
   // of rows_, cols_ and values_. If new_max_num_nonzeros is smaller
diff --git a/internal/ceres/trust_region_minimizer.h b/internal/ceres/trust_region_minimizer.h
index 8ddd77e..b5c4122 100644
--- a/internal/ceres/trust_region_minimizer.h
+++ b/internal/ceres/trust_region_minimizer.h
@@ -51,9 +51,9 @@
   ~TrustRegionMinimizer();
 
   // This method is not thread safe.
-  virtual void Minimize(const Minimizer::Options& options,
-                        double* parameters,
-                        Solver::Summary* solver_summary);
+  void Minimize(const Minimizer::Options& options,
+                double* parameters,
+                Solver::Summary* solver_summary) override;
 
  private:
   void Init(const Minimizer::Options& options,
diff --git a/internal/ceres/trust_region_minimizer_test.cc b/internal/ceres/trust_region_minimizer_test.cc
index 0c4ea29..952f878 100644
--- a/internal/ceres/trust_region_minimizer_test.cc
+++ b/internal/ceres/trust_region_minimizer_test.cc
@@ -75,7 +75,7 @@
   virtual ~PowellEvaluator2() {}
 
   // Implementation of Evaluator interface.
-  virtual SparseMatrix* CreateJacobian() const {
+  SparseMatrix* CreateJacobian() const final {
     CHECK(col1 || col2 || col3 || col4);
     DenseSparseMatrix* dense_jacobian =
         new DenseSparseMatrix(NumResiduals(), NumEffectiveParameters());
@@ -83,12 +83,12 @@
     return dense_jacobian;
   }
 
-  virtual bool Evaluate(const Evaluator::EvaluateOptions& evaluate_options,
-                        const double* state,
-                        double* cost,
-                        double* residuals,
-                        double* gradient,
-                        SparseMatrix* jacobian) {
+  bool Evaluate(const Evaluator::EvaluateOptions& evaluate_options,
+                const double* state,
+                double* cost,
+                double* residuals,
+                double* gradient,
+                SparseMatrix* jacobian) final {
     const double x1 = state[0];
     const double x2 = state[1];
     const double x3 = state[2];
@@ -188,9 +188,9 @@
     return true;
   }
 
-  virtual bool Plus(const double* state,
-                    const double* delta,
-                    double* state_plus_delta) const {
+  bool Plus(const double* state,
+            const double* delta,
+            double* state_plus_delta) const final {
     int delta_index = 0;
     state_plus_delta[0] = (col1  ? state[0] + delta[delta_index++] : state[0]);
     state_plus_delta[1] = (col2  ? state[1] + delta[delta_index++] : state[1]);
@@ -199,9 +199,9 @@
     return true;
   }
 
-  virtual int NumEffectiveParameters() const { return num_active_cols_; }
-  virtual int NumParameters()          const { return 4; }
-  virtual int NumResiduals()           const { return 4; }
+  int NumEffectiveParameters() const final { return num_active_cols_; }
+  int NumParameters()          const final { return 4; }
+  int NumResiduals()           const final { return 4; }
 
  private:
   const int num_active_cols_;
diff --git a/internal/ceres/trust_region_preprocessor.h b/internal/ceres/trust_region_preprocessor.h
index a6631ab..9597905 100644
--- a/internal/ceres/trust_region_preprocessor.h
+++ b/internal/ceres/trust_region_preprocessor.h
@@ -39,9 +39,9 @@
 class TrustRegionPreprocessor : public Preprocessor {
  public:
   virtual ~TrustRegionPreprocessor();
-  virtual bool Preprocess(const Solver::Options& options,
-                          ProblemImpl* problem,
-                          PreprocessedProblem* preprocessed_problem);
+  bool Preprocess(const Solver::Options& options,
+                  ProblemImpl* problem,
+                  PreprocessedProblem* preprocessed_problem) override;
 };
 
 }  // namespace internal
diff --git a/internal/ceres/trust_region_preprocessor_test.cc b/internal/ceres/trust_region_preprocessor_test.cc
index 40338c1..c344812 100644
--- a/internal/ceres/trust_region_preprocessor_test.cc
+++ b/internal/ceres/trust_region_preprocessor_test.cc
@@ -143,7 +143,7 @@
 
 class LinearSolverAndEvaluatorCreationTest : public ::testing::Test {
  public:
-  virtual void SetUp() {
+  void SetUp() final {
     x_ = 1.0;
     y_ = 1.0;
     z_ = 1.0;
diff --git a/internal/ceres/trust_region_strategy.h b/internal/ceres/trust_region_strategy.h
index b3b2e5d..5751691 100644
--- a/internal/ceres/trust_region_strategy.h
+++ b/internal/ceres/trust_region_strategy.h
@@ -73,6 +73,11 @@
     DoglegType dogleg_type = TRADITIONAL_DOGLEG;
   };
 
+  // Factory.
+  static TrustRegionStrategy* Create(const Options& options);
+
+  virtual ~TrustRegionStrategy();
+
   // Per solve options.
   struct PerSolveOptions {
     // Forcing sequence for inexact solves.
@@ -107,8 +112,6 @@
     LinearSolverTerminationType termination_type = LINEAR_SOLVER_FAILURE;
   };
 
-  virtual ~TrustRegionStrategy();
-
   // Use the current radius to solve for the trust region step.
   virtual Summary ComputeStep(const PerSolveOptions& per_solve_options,
                               SparseMatrix* jacobian,
@@ -133,9 +136,6 @@
 
   // Current trust region radius.
   virtual double Radius() const = 0;
-
-  // Factory.
-  static TrustRegionStrategy* Create(const Options& options);
 };
 
 }  // namespace internal
diff --git a/internal/ceres/visibility_based_preconditioner.h b/internal/ceres/visibility_based_preconditioner.h
index 31ba171..aa582d5 100644
--- a/internal/ceres/visibility_based_preconditioner.h
+++ b/internal/ceres/visibility_based_preconditioner.h
@@ -140,13 +140,13 @@
   virtual ~VisibilityBasedPreconditioner();
 
   // Preconditioner interface
-  virtual void RightMultiply(const double* x, double* y) const;
-  virtual int num_rows() const;
+  void RightMultiply(const double* x, double* y) const final;
+  int num_rows() const final;
 
   friend class VisibilityBasedPreconditionerTest;
 
  private:
-  virtual bool UpdateImpl(const BlockSparseMatrix& A, const double* D);
+  bool UpdateImpl(const BlockSparseMatrix& A, const double* D) final;
   void ComputeClusterJacobiSparsity(const CompressedRowBlockStructure& bs);
   void ComputeClusterTridiagonalSparsity(const CompressedRowBlockStructure& bs);
   void InitStorage(const CompressedRowBlockStructure& bs);